文章目录
- 1. 题目
- 2. 解题
- 2.1 暴力法
- 2.2 二分查找
1. 题目
给定一个 n x n 矩阵,其中每行和每列元素均按升序排序,找到矩阵中第k小的元素。
请注意,它是排序后的第k小元素,而不是第k个元素。
示例:
matrix = [[ 1, 5, 9],[10, 11, 13],[12, 13, 15]
],
k = 8,返回 13。
说明:
你可以假设 k 的值永远是有效的, 1 ≤ k ≤ n^2 。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/kth-smallest-element-in-a-sorted-matrix
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
2. 解题
2.1 暴力法
- 将所有元素插入小顶堆
- 然后出队k-1个,最后的堆顶就是答案,时间复杂度 O(n2)
class Solution {
public:int kthSmallest(vector<vector<int>>& matrix, int k) {priority_queue<int,vector<int>,greater<int>> q;for(auto row : matrix)for(auto elem : row)q.push(elem);while(--k)q.pop();return q.top();}
};
2.2 二分查找
- 找出矩阵中最小数left,最大数right,第k小的数在left~right之间
mid=(left+right) / 2
;在矩阵中寻找小于等于mid的元素个数count- 若
count<k
,第k小的数在右半部分且不包含mid,即left=mid+1, right=right
- 若
count>=k
,第k小的数在左半部分且可能包含mid,即left=left, right=mid
- 当
left==right
时,第k小的数即被找出
class Solution {
public:int kthSmallest(vector<vector<int>>& m, int k) {int r = m.size(), c = m[0].size();int left = m[0][0], right = m[r-1][c-1], mid, count;while(left < right){mid = left+((right-left)>>1);count = findNotBigerThanMid(m,mid,r,c);if(count < k)left = mid+1;elseright = mid;}return left;}int findNotBigerThanMid(vector<vector<int>> &m, int &mid, int &r, int &c){int i = r-1, j = 0, count = 0;while(i >= 0 && j < c){ //在左下角从下往上找,走台阶状路线,复杂度 O(n)//或者在右上角,一样的道理,跟if(m[i][j] <= mid){count += i+1;j++;}elsei--;}return count;}
};
上面的辅助求count函数,还可写成
int findNotBigerThanMid(vector<vector<int>> &m, int &mid, int &r, int &c)
{int i = 0, j = c-1, count = 0;while(i < r && j >= 0){if(m[i][j] <= mid){count += j+1;i++;}elsej--;}return count;
}
参考 Leetcode 240 搜索二维矩阵 II