一.递增矩阵查找
1) 74. Search a 2D Matrix
该题的matrix为蛇型有序,即某一行的第一个元素大于上一行的最后一个元素
2)240. Search a 2D Matrix II
该题和Search a 2D Matrix的区别在于matrix不是蛇型有序的,而是每一行每一列分别递增。
3)378. Kth Smallest Element in a Sorted Matrix
该题同第240题,matrix不是蛇型有序的,而是每一行每一列分别递增,需要寻找矩阵中第k小的元素,矩阵中可能有重复元素。
方法一:
使用priority_queue
class Solution {
public:
int kthSmallest(vector<vector<int>>& matrix, int k) {
int res=0;
int len = matrix.size();
auto cmp = [matrix](const pair<int,int> & p1,const pair<int,int> & p2)
{
return matrix[p1.first][p1.second]>matrix[p2.first][p2.second];
};
priority_queue<pair<int,int>,vector<pair<int,int>>,decltype(cmp)> que(cmp);
for(int i=0;i<len;i++)
{
que.push(make_pair(i,0));
}
pair<int,int> tmp;
while(k--)
{
tmp = que.top();
que.pop();
if(tmp.second<len-1)
que.push(make_pair(tmp.first,tmp.second+1));
}
return matrix[tmp.first][tmp.second];
}
};
能通过百分之90的用例,剩余用例超时
方法二:使用二分查找
class Solution {
public:
int kthSmallest(vector<vector<int>>& matrix, int k) {
int len = matrix.size();
int lb = matrix[0][0];
int ub = matrix[len-1][len-1];
while(lb<ub)
{
int cnt = 0;
int mid = (lb+ub)/2;
for(int i=0;i<len;i++)
{
cnt=cnt+(upper_bound(matrix[i].begin(),matrix[i].end(),mid)-matrix[i].begin());
}
if(cnt<k)
lb=mid+1;
else
ub=mid;
}
return lb;
}
};
二分查找:
这里lb和ub分别的意义为:
lb:在lb左边的一个元素lb-1(以及小于lb的所有元素),一定符合某某条件(本题为小于等于lb-1的元素的个数小于k),但是lb本身满足什么条件是在退出循环之前暂时无法知道的
ub:ub元素本身(以及大于等于ub的所有元素),一定符合某某条件(本题为小于等于lb-1的元素的个数大于等于k)
那么lb和ub最终会变为n和n+1,根据上面的分析,小于n的数一定符合:矩阵中小于等于该数的个数一定小于k,大于等于n+1的数一定符合:矩阵中小于等于该数的个数一定大于等于k。但是n满足什么条件在最后一次判断之前是无法知道的,通过最后一次判断可以最终确定一个数,小于这个数的所有数满足条件:矩阵中小于等于该数的个数一定小于k,大于等于这个数的所有数满足条件:矩阵中小于等于该数的个数一定大于等于k。
最终可以确定这个数就是要寻找的答案。
二.有序数据结构第几小数查找
1) 264. Ugly Number II
基本的思路是确定可能是下一个数的三个候选者,通过比较确定选择哪一个数,再找出三个候选者,依次类推。
class Solution {
public:
int nthUglyNumber(int n) {
vector<int> k(n,0);
k[0]=1;
int t2=0,t3=0,t5=0;
for(int i=1;i<n;i++)
{
k[i]=min(k[t2]*2,min(k[t3]*3,k[t5]*5));
if(k[i]==k[t2]*2)
t2++;
if(k[i]==k[t3]*3)
t3++;
if(k[i]==k[t5]*5)
t5++;
}
return k[n-1];
}
};
2) 378. Kth Smallest Element in a Sorted Matrix
同上文
3)373. Find K Pairs with Smallest Sums
可以AC,使用priority_queue,但是还有优化的余地
class Solution {
public:
vector<vector<int>> kSmallestPairs(vector<int>& nums1, vector<int>& nums2, int k) {
vector<vector<int>> res;
if(k==0)
return res;
//vector<int> index(nums1.size(),0);
auto cmp = [nums1,nums2](pair<int,int>& p1,pair<int,int>& p2)
{
return nums1[p1.first]+nums2[p1.second]>nums1[p2.first]+nums2[p2.second];
};
priority_queue<pair<int,int>,vector<pair<int,int>>,decltype(cmp)> que(cmp);
for(int i=0;i<nums1.size();i++)
{
if(!nums2.empty())
que.push(make_pair(i,0));
}
pair<int,int> temp;
while(k--&&!que.empty())
{
temp = que.top();
que.pop();
res.push_back(vector<int>{nums1[temp.first],nums2[temp.second]});
if(temp.second+1<nums2.size())
que.push(make_pair(temp.first,temp.second+1));
}
return res;
}
};
4)719. Find K-th Smallest Pair Distance
使用priority_queue,会超内存,部分用例过不了:
class Solution {
public:
int smallestDistancePair(vector<int>& nums, int k) {
sort(nums.begin(),nums.end());
auto cmp = [nums](pair<int,int> p1,pair<int,int> p2)
{
return nums[p1.second]-nums[p1.first]> nums[p2.second]-nums[p2.first];
};
priority_queue<pair<int,int>,vector<pair<int,int>>,decltype(cmp)> que(cmp);
for(int i=0;i<nums.size()-1;i++)
{
que.push(make_pair(i,i+1));
}
pair<int,int> temp;
while(k--)
{
temp=que.top();
que.pop();
if(temp.second<nums.size()-1)
que.push(make_pair(temp.first,temp.second+1));
}
return nums[temp.second]-nums[temp.first];
}
};
使用二分法可以AC