• 找到排序矩阵中从小到大第K个数字


    一 题目描述

    在一个排序矩阵中找从小到大的第 k 个整数。

    排序矩阵的定义为:每一行递增,每一列也递增。

    二 题解

    由于排序矩阵中的每一行都是递增的,并且每一列都是递增的。从小到大第k个数,实际上就是第k小的数。思路如下:

    假设排序矩阵共有row行和col列,由于每行是递增的,我们只要选择出每行的最小数(一共row个)并从这row个数中选出最小的数来,重复这个过程k次,第k次选择出的最小值就是整个矩阵中第k小的数。

    代码如下:

    class Solution
    {
    public:
        /**
         * @param matrix: a matrix of integers
         * @param k: An integer
         * @return: the kth smallest number in the matrix
         */
        int kthSmallest(vector<vector<int>> &matrix, int k)
        {
            size_t row = matrix.size();
            size_t col = matrix[0].size();
            if(row == 0 || col == 0)
                return -1;
            int minRows[row];//用于存储每行的最小值对应的列数
            memset(minRows,0,sizeof(minRows));//对minRows初始化,且初始值都为0
            if(k > row * col)//错误处理
                return -1;
            int rs;
            int tmp;
            for(int cnt = 1; cnt <= k; cnt++)
            {
                int min_val = INT_MAX;//每次比较都需要初始化,注意该变量定义的位置
                for(int row_index = 0; row_index < row; row_index++)
                {
                    if(minRows[row_index] < col)//注意这个判断条件一定要加上,防止越界
                    {
                        if(matrix[row_index][minRows[row_index]] < min_val)
                        {
                            min_val = matrix[row_index][minRows[row_index]];
                            tmp = row_index;
                        }
                    }
                }
                minRows[tmp]++;//更新相应行中最小值的位置,要注意此处的位置,是在row轮循环之后才能找出最小值
                if(cnt == k)
                    rs = min_val;
            }
            return rs;
        }
    };
    

    该算法思路表简单,算法的时间复杂度为O(k*row),此外,有几个需要注意的地方:

    1.我们每次选择出的最小值指的是这row个数中的最小值,所以mi_val这个变量需要在每次循环开始的时候才定义,这里我定义的是INT_MAX,所以所有的行需要遍历一一遍。

    2.在每次进行row轮循环的时候,一定不要忘记判断,相应的值的列数的索引是否已经达到最大值。

    3.注意minRows数组更新的时候是在row轮循环结束的后才进行更新。

    ============================================================================================================

    此外,本题是从列的角度来考虑的,即每次找出一列数中的最小值来;,当然也可从行的角度来考虑,每次找出一行数中的最小值来,重复k次,第k次的最小值就是最终结果。两种方法思想类似,利用第二种方法的话时间复杂度就变成了O(k*col)。

    当列数大于行数的时候,用第一种方法比较好;而当行数大于列数的时候用第二种方法比较好,当然前提是行数和列数的差值比较大,否则两种方法性能差不多;当然,也可以结合这两种情况,对于行列数不同的情况时,采用不同方法。

  • 相关阅读:
    大数据学习总结(7)we should...
    大数据学习总结(6)what is our foucus
    洛谷P4632 [APIO2018] New Home 新家(动态开节点线段树 二分答案 扫描线 set)
    BZOJ5249: [2018多省省队联测]IIIDX(线段树 贪心)
    BZOJ2438: [中山市选2011]杀人游戏(tarjan)
    cf1072D. Minimum path(BFS)
    cf1072B. Curiosity Has No Limits(枚举)
    cf567E. President and Roads(最短路计数)
    六校联考考试反思
    BZOJ4010: [HNOI2015]菜肴制作(拓扑排序 贪心)
  • 原文地址:https://www.cnblogs.com/wangkundentisy/p/9388378.html
Copyright © 2020-2023  润新知