leetcode题型归纳:递增矩阵查找和有序数据结构第几小数查找

一.递增矩阵查找

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值