有序矩阵中第K小的元素-leetcode378

题目描述

给定一个 n x n 矩阵,其中每行和每列元素均按升序排序,找到矩阵中第 k 小的元素。
请注意,它是排序后的第 k 小元素,而不是第 k 个不同的元素。

示例:

matrix = [
[ 1, 5, 9],
[10, 11, 13],
[12, 13, 15]
],
k = 8,

返回 13。

提示:

你可以假设 k 的值永远是有效的,1 ≤ k ≤ n2 。

思路:

  • 本题我能想到2种解法:
    • 归并排序:每一行都是有序的,可以全部合并在一起然后查找第k个元素就行。
    • 二分查找:利用 爬格子 一样的方法得知矩阵中有多少个元素小于 Matrix[0][0] - Matrix[n-1][n-1](mid)。
      • cnt为矩阵中小于mid的个数,此时可以将矩阵抽象为列表
      • cnt,则说明第k个元素在mid右边。
      • cnt>k,则说明第k个元素在mid左边。
      • cnt=k,则说明第k个元素在此时的mid。
        有序矩阵中第K小的元素-leetcode378_第1张图片

代码:

class Solution {
public:
    int kthSmallest(vector<vector<int>>& matrix, int k) {
        int n = matrix.size();
        int left = matrix[0][0];
        int right = matrix[n-1][n-1];
        int mid = (left + right) >> 1;
        while(left < right){
            if(check(matrix,mid,k,n)){
                right = mid;
            } else{
                left = mid+ 1;
            }
            mid = (left + right) >> 1;
        }
        return left;
    }
    bool check(vector<vector<int>>&matrix,int mid,int k,int n){
        int row = 0;
        int col = n-1;
        int cnt = 0;
        while(row <= n-1  && col >= 0){
            if(matrix[col][row] <= mid){
                cnt = cnt + col + 1;
                row++;
            }else {
                col--;
            }
        }
        return cnt >= k;
    }
};

总结:

  • 如果计算mid时,使用int mid = (left + right) >> 1,会出现Line 7: Char 25: runtime error: signed integer overflow: 2000000000 + 2000000000 cannot be represented in type 'int' (solution.cpp)两个大数相加会溢出,可以使用int mid = left + ((right - left) >> 1)
  • 二维数组搜索用这种爬格子的方法害挺好玩的。
  • 边界条件好烦

你可能感兴趣的:(每日一题)