k-th smallest 问题总结
k-th smallest/biggest 问题大约有这几道:
373. Find K Pairs with Smallest Sums | 从两个list里各取一个数求和,求所有可能的sum里第k小的 |
378. Kth Smallest Element in a Sorted Matrix | 给一个每一横排/每一纵列都有序的matrix,求其中第k小的元素 |
668. Kth Smallest Number in Multiplication Table | 给一个乘法表(类似378的matrix),求其中第k小的元素 |
719. Find K-th Smallest Pair Distance | 从一个list里取两个元素求和,求所有可能的sum里第k小的 |
786. K-th Smallest Prime Fraction | 从一个list里取两个元素相除,求所有可能的sum里第k小的 |
可以看出,其实373 719 786是同一题,378 668是同一题
这种题大致有两种思路:
1. 用heap
关于堆的介绍网上有一大把......这里只划重点
堆是一种是一种特殊的完全二叉树,其中每个根节点一定比它的左、右儿子节点都大/小(大根堆or小根堆)。每次增/删元素时,需要移动二叉树节点来保持这一性质。
时间复杂度:
从一个长度为N的乱序数组建堆 O(NlogN)
向长度为N的堆插入/删除一个元素 O(logN)
实现:
C++里可以用priority_queue<int> pq。常用操作有push(), pop(), top(), empty(), size()
Python 里可以用import heapq,然后heapq.heapify(list_a)就在原list上建好堆啦,a[0]就是堆顶。不过它只能建大根堆
- import heapq
- #heapq implemented min heap only. Thus we save -nums[i] into the heap
- class Solution:
- def maxSlidingWindow(self, nums, k):
- """
- :type nums: List[int]
- :type k: int
- :rtype: List[int]
- """
- a=[]
- res=[]
- for i in range(len(nums)):
- a.append(-nums[i])
- if(i>=k):
- a.remove(-nums[i-k])
- heapq.heapify(a)
- if(i>=k-1):
- res.append(-a[0])
- return res
- sl=Solution()
- nn=[1,3,-1,-3,5,3,6,7]
- rr=sl.maxSlidingWindow(nn,3)
- print(rr)
Python的implementation实例(LeetCode 239的弱鸡解法)
解题思路:
把所有要比较的东西都塞到heap里,最后做k次取堆顶--弹出堆顶的操作
时间复杂度是 O(N^2 * log(N^2)) 有些medium题能过,但hard题肯定不行
根据题目具体情况,一开始不一定所有的东西都要塞进heap
例题:
373. Find K Pairs with Smallest Sums
反正过是能过...它的加强版就是719 786啦
priority_queue默认是大根堆,要是想要小根堆需要自定义比较函数。这里我直接重载了运算符(因为是pair嘛),推荐一下这种写法(骄傲
- class Solution {
- public:
- struct Node
- {
- pair<int, int> val;
- Node(int x,int y) {val=pair<int, int>(x,y);}
- bool operator <(Node a) const {return(val.first+val.second < a.val.first+a.val.second);}
- bool operator >(Node a) const {return(val.first+val.second > a.val.first+a.val.second);}
- };
- vector<pair<int, int>> kSmallestPairs(vector<int>& nums1, vector<int>& nums2, int k)
- {
- vector< pair<int, int> > ans;
- int lx=nums1.size(),ly=nums2.size();
- if(lx== || ly==) return ans;
- k=min(k,lx*ly);
- priority_queue<Node, vector<Node>, greater<Node> > pq;
- for(int i=;i<min(lx,k);i++)
- for(int j=;j<min(ly,k);j++)
- {
- pq.push(Node(nums1[i], nums2[j]));
- }
- while(k)
- {
- ans.push_back(pq.top().val);
- pq.pop();
- k--;
- }
- return ans;
- }
- };
378. Kth Smallest Element in a Sorted Matrix
赤果果的heap。又不是不能用......
- //O(N*N*log(N*N))
- class Solution {
- public:
- int kthSmallest(vector<vector<int>>& matrix, int k)
- {
- int dx=matrix.size(),dy=matrix[].size();
- priority_queue<int> pq;
- for(int i=;i<dx;i++)
- for(int j=;j<dy;j++)
- pq.push(matrix[i][j]);
- int ans;
- k=dx*dy-k+;
- while(k)
- {
- ans=pq.top();
- pq.pop();
- k--;
- }
- return ans;
- }
- };
另外三题heap都是妥妥超时的噢......hard就是hard
2. Binary Search
二分查找模板了解一下:
under_construction
时间复杂度:
O(log(N))
解题思路:
用二分查找(有left, right, mid)来枚举第k小的值,然后看原数组里当前有多少是小于mid的,多了就减小right,少了就增大left。直到查找结束,此时left就是第k小值啦
实现时先对原数组按行/列排个序,或者题目本身就是保证有序的
时间复杂度是 O(log(X)*N) ,其中log(X)是二分查找的开销(X=right-left),N是在原数组里找小于mid的数的开销(二维数组的话最坏情况可能会N^2,不过一般也能过)
例题:
378. Kth Smallest Element in a Sorted Matrix
就按上面的方法实现哒
在原数组里count时用了一个函数upper_bound(matrix[i].begin(), matrix[i].end(), mid),返回matrix[i]这个从小到大有序的vector里小于等于mid的第一个数的指针
这玩意底层是二分查找,时间复杂度是logN呢。
- //O(N*log(N)*log(max-min))
- //Binary Search
- class Solution {
- public:
- int kthSmallest(vector<vector<int>>& matrix, int k)
- {
- int dx=matrix.size(),dy=matrix[].size();
- int ml=matrix[][], mr=matrix[dx-][dy-];
- int mid,cnt;
- while(ml<mr)
- {
- mid=(ml+mr)/;
- cnt=;
- for(int i=;i<dx;i++)
- {
- cnt+=upper_bound(matrix[i].begin(), matrix[i].end(), mid)-matrix[i].begin();
- }
- if(cnt>=k)
- mr=mid;
- else if(cnt<k)
- ml=mid+;
- }
- return ml;
- }
- };
668. Kth Smallest Number in Multiplication Table
上面的改巴改巴就行了......
- //Binary Search
- class Solution {
- public:
- //int kthSmallest(vector<vector<int>>& matrix, int k)
- int findKthNumber(int m, int n, int k)
- {
- int ml=, mr=m*n;
- int mid,cnt;
- while(ml<mr)
- {
- mid=(ml+mr)/;
- cnt=;
- for(int i=;i<=m;i++)
- {
- cnt+=min(mid/i,n);
- }
- if(cnt>=k)
- mr=mid;
- else if(cnt<k)
- ml=mid+;
- }
- return ml;
- }
- };
719. Find K-th Smallest Pair Distance
一样的套路噢...就是从一个matrix变成了两个list
- // Binary Search
- class Solution {
- public:
- int smallestDistancePair(vector<int>& nums, int k)
- {
- int n=nums.size();
- sort(nums.begin(), nums.end());
- int ml=nums[]-nums[],mr=nums[n-]-nums[],mid=,cnt=;
- for(int i=;i<n-;i++) ml=min(ml,nums[i+]-nums[i]);
- while(ml<mr)
- {
- mid=(ml+mr)/;
- cnt=;
- for(int i=;i<n;i++)
- {
- int j=i+;
- while(j<n && nums[j]-nums[i]<=mid) j++;
- cnt+=(j-i-);
- }
- if(cnt<k)
- ml=mid+;
- else
- mr=mid;
- }
- return ml;
- }
- };
这题其实还有个骚操作:因为list值的范围比较小,所以可以用counting sort:先用O(N^2)的时间把所有可能的pair和记下来,然后在counting sort的数组里从小到大数数即可
不过感觉这方法通用性应该不强...
- //counting sort: O(N^2)
- class Solution {
- public:
- int smallestDistancePair(vector<int>& nums, int k)
- {
- int val[];
- memset(val,,sizeof(val));
- int nl=nums.size();
- for(int i=;i<nl;i++)
- for(int j=i+;j<nl;j++)
- {
- //cout<<abs(nums[j]-nums[i])<<endl;
- val[abs(nums[j]-nums[i])]++;
- }
- int ans=;
- while(k)
- {
- if(val[ans]>)
- {
- //cout<<k<<" "<<ans<<endl;
- val[ans]--;
- k--;
- }
- else ans++;
- }
- return ans;
- }
- };
786. K-th Smallest Prime Fraction
这题坑多一点,因为是分数,涉及到浮点数嘛
涉及到浮点数就不能直接用=比较辣,要用r-l<eps。
以及注意两个int做除法,要先强制转换成double
- //Binary Search, AC
- class Solution {
- public:
- vector<int> kthSmallestPrimeFraction(vector<int>& A, int k)
- {
- vector<int> ans;
- int al=A.size();
- sort(A.begin(), A.end());
- double ml=0.0, mr=1.0, md=0.5;
- int dx,dy,cnt;
- double eps=1e-;
- while(mr-ml>eps)
- {
- md=(ml+mr)/;
- cnt=;
- for(int i=;i<al;i++)
- {
- int j=al-;
- while(j>i && (double)A[i]/(double)A[j]<md) j--;
- cnt+=(al--j);
- }
- cout<<ml<<","<<mr<<"=="<<md<<" "<<cnt<<endl;
- if(cnt<k)
- ml=md;
- else
- mr=md;
- }
- for(int i=;i<al;i++)
- for(int j=i+;j<al;j++)
- if(abs((double)A[i]/(double)A[j] - ml)<eps)
- {
- dx=A[i]; dy=A[j];
- ans.push_back(dx); ans.push_back(dy);
- return(ans);
- }
- return ans;
- }
- };
k-th smallest 问题总结的更多相关文章
- [Swift]LeetCode786. 第 K 个最小的素数分数 | K-th Smallest Prime Fraction
A sorted list A contains 1, plus some number of primes. Then, for every p < q in the list, we co ...
- [LeetCode] K-th Smallest Prime Fraction 第K小的质分数
A sorted list A contains 1, plus some number of primes. Then, for every p < q in the list, we co ...
- [Algorithm] How to use Max Heap to maintain K smallest items
Let's say we are given an array: [,,,,,,] We want to get K = 3 smallest items from the array and usi ...
- [LeetCode] 786. K-th Smallest Prime Fraction 第K小的质分数
A sorted list A contains 1, plus some number of primes. Then, for every p < q in the list, we co ...
- Find the largest K numbers from array (找出数组中最大的K个值)
Recently i was doing some study on algorithms. A classic problem is to find the K largest(smallest) ...
- 【转载】两个排序数组的中位数 / 第K大元素(Median of Two Sorted Arrays)
转自 http://blog.csdn.net/zxzxy1988/article/details/8587244 给定两个已经排序好的数组(可能为空),找到两者所有元素中第k大的元素.另外一种更加具 ...
- 算法打基础——顺序统计(找第k小数)
这次主要是讲如何在线性时间下找n个元素的未排序序列中第k小的数.当然如果\(k=1 or k=n\),即找最大最小 数,线性时间内遍历即可完成,当拓展到一般,如中位数时,相关算法就值得研究了.这里还要 ...
- HDU - 6041:I Curse Myself(Tarjan求环&K路归并)
There is a connected undirected graph with weights on its edges. It is guaranteed that each edge app ...
- 786. K-th Smallest Prime Fraction
A sorted list A contains 1, plus some number of primes. Then, for every p < q in the list, we co ...
- LeetCode 4 Median of Two Sorted Arrays (两个数组的mid值)
题目来源:https://leetcode.com/problems/median-of-two-sorted-arrays/ There are two sorted arrays nums1 an ...
随机推荐
- EasyARM-iMX283A的U盘使用教程
在编写代码前我们先来EasyARM-iMX283A对U盘使用的操作. 我们先拿一个U盘进行格式化 在U盘中写一些文件保存后,弹出U盘. 将U盘插入EasyARM-iMX283A的开发板. [注意]Ea ...
- 【FZSZ2017暑假提高组Day1】确定小组
[问题描述] 有n个人坐成一排,这n个人都在某一个小组中,同一个小组的所有人所坐的位置一定是连续的. 有一个记者在现场进行采访,他每次采访都会询问一个人其所在的小组有多少人,被询问的每个人都给出了正确 ...
- 去BAT,你应该要看一看的面试经验总结(转)
来源微信公众号『easyserverdev』 http://mp.weixin.qq.com/s/UZljzFMjobo1wzCguY7NDg 说下我的面试经验吧,都是亲身经历,不喜勿喷: 我去年12 ...
- 服务器解析慢,可以安装nscd解决
针对服务器解析慢,可以在服务器上安装nscd,就可以把解析缓存起来,不用每次都解析 安装nscd: yum -y install nscd chkconfig nscd on service nscd ...
- js 一些兼容检测
1. IE5.0之前不支持 document.getElementById(),但存在 document.all[] function getElementById(id) { if(document ...
- db2常见命令
增加db2top命令的refresh间隔,默认值为2秒,下面的命令就可以每10秒刷新一次: $ db2top -i 10 -d sample 数据库本身太繁忙(dynamic SQL过多).建议增加 ...
- android 字体加粗
参考 https://blog.csdn.net/to_cm/article/details/6002812 TextView tv = (TextView)findViewById(R.id.Tex ...
- 图像处理项目——生成csv文件提高读取效率
利用pyhton脚本生成csv文件 *开发环境为windows PyCharm*使用的是pyhton脚本*生成人脸和人脸对应的标签的csv文件 一:主要步骤 1.载入对应路径2.提取每一张图片对应的位 ...
- HDU6446 Tree and Permutation(树上DP)
传送门:点我 Tree and Permutation Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (J ...
- mybatis pagehelper分页插件使用
使用过mybatis的人都知道,mybatis本身就很小且简单,sql写在xml里,统一管理和优化.缺点当然也有,比如我们使用过程中,要使用到分页,如果用最原始的方式的话,1.查询分页数据,2.获取分 ...