Given a n x n matrix where each of the rows and columns are sorted in ascending order, find the kth smallest element in the matrix.

Note that it is the kth smallest element in the sorted order, not the kth distinct element.

Example:

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

Note:
You may assume k is always valid, 1 ≤ k ≤ n2.

这道题让我们求有序矩阵中第K小的元素,这道题的难点在于数组并不是蛇形有序的,意思是当前行的最后一个元素并不一定会小于下一行的首元素,所以我们并不能直接定位第K小的元素,所以只能另辟蹊径。先来看一种利用堆的方法,我们使用一个最大堆,然后遍历数组每一个元素,将其加入堆,根据最大堆的性质,大的元素会排到最前面,然后我们看当前堆中的元素个数是否大于k,大于的话就将首元素去掉,循环结束后我们返回堆中的首元素即为所求:

解法一:

class Solution {
public:
int kthSmallest(vector<vector<int>>& matrix, int k) {
priority_queue<int> q;
for (int i = ; i < matrix.size(); ++i) {
for (int j = ; j < matrix[i].size(); ++j) {
q.emplace(matrix[i][j]);
if (q.size() > k) q.pop();
}
}
return q.top();
}
};

这题我们也可以用二分查找法来做,我们由于是有序矩阵,那么左上角的数字一定是最小的,而右下角的数字一定是最大的,所以这个是我们搜索的范围,然后我们算出中间数字mid,由于矩阵中不同行之间的元素并不是严格有序的,所以我们要在每一行都查找一下 mid,我们使用 upper_bound,这个函数是查找第一个大于目标数的元素,如果目标数在比该行的尾元素大,则 upper_bound 返回该行元素的个数,如果目标数比该行首元素小,则 upper_bound 返回0, 我们遍历完所有的行可以找出中间数是第几小的数,然后k比较,进行二分查找,left 和 right 最终会相等,并且会变成数组中第k小的数字。举个例子来说吧,比如数组为:

[1 2
12 100]
k = 3
那么刚开始 left = 1, right = 100, mid = 50, 遍历完 cnt = 3,此时 right 更新为 50
此时 left = 1, right = 50, mid = 25, 遍历完之后 cnt = 3, 此时 right 更新为 25
此时 left = 1, right = 25, mid = 13, 遍历完之后 cnt = 3, 此时 right 更新为 13
此时 left = 1, right = 13, mid = 7, 遍历完之后 cnt = 2, 此时 left 更新为8
此时 left = 8, right = 13, mid = 10, 遍历完之后 cnt = 2, 此时 left 更新为 11
此时 left = 11, right = 12, mid = 11, 遍历完之后 cnt = 2, 此时 left 更新为 12
循环结束,left 和 right 均为 12,任意返回一个即可。

本解法的整体时间复杂度为 O(nlgn*lgX),其中X为最大值和最小值的差值,参见代码如下:

解法二:

class Solution {
public:
int kthSmallest(vector<vector<int>>& matrix, int k) {
int left = matrix[][], right = matrix.back().back();
while (left < right) {
int mid = left + (right - left) / , cnt = ;
for (int i = ; i < matrix.size(); ++i) {
cnt += upper_bound(matrix[i].begin(), matrix[i].end(), mid) - matrix[i].begin();
}
if (cnt < k) left = mid + ;
else right = mid;
}
return left;
}
};

上面的解法还可以进一步优化到 O(nlgX),其中X为最大值和最小值的差值,我们并不用对每一行都做二分搜索法,我们注意到每列也是有序的,我们可以利用这个性质,从数组的左下角开始查找,如果比目标值小,我们就向右移一位,而且我们知道当前列的当前位置的上面所有的数字都小于目标值,那么 cnt += i+1,反之则向上移一位,这样我们也能算出 cnt 的值。其余部分跟上面的方法相同,参见代码如下:

解法三:

class Solution {
public:
int kthSmallest(vector<vector<int>>& matrix, int k) {
int left = matrix[][], right = matrix.back().back();
while (left < right) {
int mid = left + (right - left) / ;
int cnt = search_less_equal(matrix, mid);
if (cnt < k) left = mid + ;
else right = mid;
}
return left;
}
int search_less_equal(vector<vector<int>>& matrix, int target) {
int n = matrix.size(), i = n - , j = , res = ;
while (i >= && j < n) {
if (matrix[i][j] <= target) {
res += i + ;
++j;
} else {
--i;
}
}
return res;
}
};

Github 同步地址:

https://github.com/grandyang/leetcode/issues/378

类似题目:

Find K Pairs with Smallest Sums

Find K-th Smallest Pair Distance

Find K Closest Elements

Kth Smallest Number in Multiplication Table

K-th Smallest Prime Fraction

参考资料:

https://leetcode.com/problems/kth-smallest-element-in-a-sorted-matrix/

https://leetcode.com/problems/kth-smallest-element-in-a-sorted-matrix/discuss/85177/Java-1ms-nlog(max-min)-solution

https://leetcode.com/problems/kth-smallest-element-in-a-sorted-matrix/discuss/85222/C%2B%2B-priority-queue-solution-O(klogn)

https://leetcode.com/problems/kth-smallest-element-in-a-sorted-matrix/discuss/85182/My-solution-using-Binary-Search-in-C%2B%2B

LeetCode All in One 题目讲解汇总(持续更新中...)

[LeetCode] Kth Smallest Element in a Sorted Matrix 有序矩阵中第K小的元素的更多相关文章

  1. [LeetCode] 378. Kth Smallest Element in a Sorted Matrix 有序矩阵中第K小的元素

    Given a n x n matrix where each of the rows and columns are sorted in ascending order, find the kth ...

  2. 378 Kth Smallest Element in a Sorted Matrix 有序矩阵中第K小的元素

    给定一个 n x n 矩阵,其中每行和每列元素均按升序排序,找到矩阵中第k小的元素.请注意,它是排序后的第k小元素,而不是第k个元素.示例:matrix = [   [ 1,  5,  9],   [ ...

  3. [LintCode] Kth Smallest Number in Sorted Matrix 有序矩阵中第K小的数字

    Find the kth smallest number in at row and column sorted matrix. Have you met this question in a rea ...

  4. LeetCode 378. 有序矩阵中第K小的元素(Kth Smallest Element in a Sorted Matrix) 13

    378. 有序矩阵中第K小的元素 378. Kth Smallest Element in a Sorted Matrix 题目描述 给定一个 n x n 矩阵,其中每行和每列元素均按升序排序,找到矩 ...

  5. Leetcode 378.有序矩阵中第k小的元素

    有序矩阵中第k小的元素 给定一个 n x n 矩阵,其中每行和每列元素均按升序排序,找到矩阵中第k小的元素.请注意,它是排序后的第k小元素,而不是第k个元素. 示例: matrix = [ [ 1, ...

  6. Java实现 LeetCode 378 有序矩阵中第K小的元素

    378. 有序矩阵中第K小的元素 给定一个 n x n 矩阵,其中每行和每列元素均按升序排序,找到矩阵中第k小的元素. 请注意,它是排序后的第k小元素,而不是第k个元素. 示例: matrix = [ ...

  7. [Swift]LeetCode378. 有序矩阵中第K小的元素 | Kth Smallest Element in a Sorted Matrix

    Given a n x n matrix where each of the rows and columns are sorted in ascending order, find the kth ...

  8. 【Leetcode 堆、快速选择、Top-K问题 BFPRT】有序矩阵中第K小的元素(378)

    题目 给定一个 n x n 矩阵,其中每行和每列元素均按升序排序,找到矩阵中第k小的元素. 请注意,它是排序后的第k小元素,而不是第k个元素. 示例: matrix = [ [ 1, 5, 9], [ ...

  9. leetcode.矩阵.378有序矩阵中第K小的元素-Java

    1. 具体题目 给定一个 n x n 矩阵,其中每行和每列元素均按升序排序,找到矩阵中第k小的元素.请注意,它是排序后的第k小元素,而不是第k个元素. 示例: matrix = [ [ 1,  5, ...

随机推荐

  1. 行为驱动开发(BDD)实践示例

    引言 BDD是对TDD理念的扩展.BDD强调有利害关系的技术团体和非技术团队都要参与到软件开发过程中.可以把它看成一种强调团体间合作的敏捷方法.大多数采用某种敏捷方法的团队最终都会遵循BDD的许多原则 ...

  2. 1.C#面向对象基础简介

    学习核心内容: 面向对象的三个特性:封装.继承.多态 访问级别:用处在于控制成员在那些地方可以访问,这样达到面向对象封装的目的. 常用级别:public (任何地方都可以访问) private(默认级 ...

  3. CSS知识总结(六)

    CSS常用样式 4.段落样式 1)行高 控制段落内每行高度 line-height : normal | length 例子 源代码: /* CSS代码 */ .normal{ line-height ...

  4. 实践 HTML5 的 CSS3 Media Queries

    先来介绍下 media,确切的说应该是 CSS media queries(CSS 媒体查询),媒体查询包含了一个媒体类型和至少一个使用如宽度.高度和颜色等媒体属性来限制样式表范围的表达式.CSS3 ...

  5. nginx添加 nginx_heath模块

    原因?为什么会使用nginx_heath 这个模块,主要是如nginx+tomcat部署的时,tomcat挂了之后nginx->upstream 轮询是可以踢掉挂掉的tomcat服务的,如果部署 ...

  6. Singleton(单例模式)的一种实现 -- 基于【惰性】适用于【大对象】的一种生产实践

    一.说明 本文中的代码类,在生产中使用了很长的时间,曾应用于多个企业多个项目实践中,其中也踩了不少坑,总结了一些适用的业务情景, 重要的事情说三遍: a.本代码类不是万能药,不要在业务情景中滥用! b ...

  7. 解决ngnix服务器上的Discuz!x2.5 Upload Error:413错误

    1.修改php.ini sudo nano /etc/php5/fpm/php.ini #打开php.ini找到并修改以下的参数,目的是修改上传限制 max_execution_time = 900 ...

  8. 《C#微信开发系列(Top)-微信开发完整学习路线》

    年前就答应要将微信开发的学习路线整理给到大家,但是因为年后回来这段时间学校还有公司那边有很多事情需要兼顾,所以没能及时更新文章.今天特地花时间整理了下,话不多说,上图,希望对大家的学习有所帮助哈. 如 ...

  9. [deviceone开发]-底部弹出选择

    一.简介 个人上传的第一个示例源码,两天空闲时间写的,一点简单组件,写的挺乱还没啥注释,仅供新手学习. 底部弹出选择,可滑动选择选项,如果停留在选项中间,可自动校正位置,加了一点简单的动画效果,需要的 ...

  10. UTFGrid

    UTFGrid UTFGrid is a specification for rasterized interaction data. As of version 1.2, it was remove ...