zoukankan      html  css  js  c++  java
  • 378. 有序矩阵中第K小的元素

    题目链接

    题解:

    1 直接排序。

    最简单的方法,放到一维数组中,直接排序,时间复杂度为o((n^2)log(n^2)),空间复杂度为o(n^2),如果n>=1e4就会超时。

    代码略:

    2 堆排序。

    这种方法是很一个很巧妙的方法。充分用到了矩阵的每一行和每一列都是有序的。首先将第一列放到堆中,然后取出第一个元素,这个元素一定是最小的,然后我们在考虑第二小的,第二小的要么是它右边的元素,要么是它下边的元素,由于它下边的元素已经在堆里面了,只需要把其右边的元素放到堆里即可。即每次取一个元素,然后将该元素的右边的元素放到堆中,注意堆排序要求堆顶元素最小。然后执行k次数就可以找到了

    时间复杂度为o(klog(n))

    空间复杂度为o(n)

    由于在c++类中定义类/结构体还不太熟练,所以代码就没写。

    3 二分法。

    这种方法是最优的方法, 思路特别巧妙。注意矩阵的特点是每行每列都是有序的。所以对于每一个数我们总是可以找到一条线,该线可以把矩阵一分为二,左半部分是小于等于该数,右半部分是大于该数的。所以我们可以在时间复杂度为o(n)的情况下,来找到当前数在矩阵中有几个大于该数的,有几个小于等于该数的。也就满足二分的条件了。

    code:

    class Solution {
    public:
        int check(vector<vector<int>>& matrix, int mid,int n,int k){
            int i=n-1;
            int j=0;
            int num=0;
            while(i>=0&&j<=n-1){
                if(matrix[i][j]<=mid){
                    num+=i+1;
                    j++;
                }
                else i--;
            } 
            return num>=k;//num是比小于等于mid的元素的个数。
        }
        int kthSmallest(vector<vector<int>>& matrix, int k) {
            long  n=matrix.size();
            long  l=matrix[0][0];
            long long  r=matrix[n-1][n-1];
            long long ans=l;
            while(l<=r){
                long long  mid=(l+r)/2;
                bool c=check(matrix,mid,n,k);
                if(c){//说明小于等于mid的元素个数比k多,answer<=mid
                    r=mid-1;
                    ans=mid;
                }
                else l=mid+1;
            }
            return ans;
        }
    };

    有个问题。如果mid不在矩阵中怎么办?check函数返回值为1的时候,说明小于等于mid的元素比k多,那么answer<=mid,即让mid变小一点,check最后一次等于1时,answer一定等于mid。因为mid在小就不满足条件了。所以即便mid不再矩阵中出现,也可以找到答案。

  • 相关阅读:
    Windows10 iis10 arr webfarm
    两个command的疑惑
    关于controller和apicontroller的跨域实现过滤器的不同
    抽象工厂
    c# 字体库跨域解决
    c# 父类的引用指向子类的实例
    垂直居中
    扇形导航
    2D变换
    京东放大镜效果
  • 原文地址:https://www.cnblogs.com/Accepting/p/13306146.html
Copyright © 2011-2022 走看看