文章目录
前言
运用Scala中的语法实现有序矩阵中第K小的元素
一、有序矩阵中第K小的元素是什么?
给定一个 n x n 矩阵,其中每行和每列元素均按升序排序,找到矩阵中第 k 小的元素。 请注意,它是排序后的第 k 小元素,而不是第 k 个不同的元素。 示例: matrix = [ [ 1, 5, 9], [10, 11, 13], [12, 13, 15] ], k = 8, 返回 13。
二、具体实现
代码如下(示例):
这就是二分法的思路。假定查找的范围为[left, right],首先计算int mid = left + (right - left) / 2, 然后在矩阵中计数有多少个元素小于等于mid,这个数量为count。 如果count < k,那么第k小的数至少为mid + 1,所以left = mid + 1。 反之,right = mid。 循环结束的条件为left >= right,此时left即为答案。 def kthSmallest(matrix: Array[Array[Int]], k: Int): Int = { val len=matrix.length-1 //二分法的思路。假定查找的范围为[left, right] var left=matrix(0)(0)//left的初始值为数组中的最小值 var right=matrix(len)(len)//right的初始值为数组中的最大值 while (left < right){ val mid=left+(right-left)/2 val count=countNotMoreThanMid(matrix, mid, len);//统计多少个数小于mid if (count < k)//如果count < k,那么第k小的数至少为mid + 1,所以left = mid + 1。 left=mid+1 else//反之,第k小的数最多为mid + 1,right = mid。 right=mid } left }
def countNotMoreThanMid(matrix: Array[Array[Int]], mid: Int, len: Int)={ var count = 0 var i=0 var j=len //从左下角开始找 while (i<=len && j>=0) if(matrix(i)(j) <= mid){//如何mid值大于当前值,肯定大于当前值所在列的前j行值 count += j + 1;//count=j+1 i+=1//往右移动一列 }else{ j-=1如何mid值小于当前值,往上移动一行 } count }
例如 mid=8:
我们可以看到,矩阵中大于 midmid 的数就和不大于 midmid 的数分别形成了两个板块,沿着一条锯齿线将这个矩形分开。其中左上角板块的大小即为矩阵中不大于 midmid 的数的数量。