题目:
给你一个 n x n **矩阵 matrix ,其中每行和每列元素均按升序排序,找到矩阵中第 k 小的元素。
请注意,它是 排序后 的第 k 小元素,而不是第 k 个 不同 的元素。
你必须找到一个内存复杂度优于 O(n2) 的解决方案。
算法:
方法一:二分查找
func kthSmallest(matrix [][]int, k int) int {
// start,end是左上到右下的对角线位置的value,找到这个递增关系
n := len(matrix)
start, end := matrix[0][0], matrix[n - 1][n - 1]
for start < end {
// 数组有负数的时候要小心
// (start + end) / 2是向0取整,负数的时候和正数行为不一样
// start + (end - start) / 2 取得是数组的左边界
mid := start + (end - start) / 2
count := check(matrix, mid)
fmt.Println(mid, count, start, end)
// mid划分了[left , mid] 与[mid + 1, right]两部分
// 这里是要用逼近,将start,end压缩压缩
// count==k不能直接返回
// 因为讲难听的点right是否存在matrix中是不确定的,因为start + (end - start) / 2 取得是数组的左边界
if count >= k {
end = mid
} else {
start = mid + 1
}
}
// start一定存在matrix中,假设第k和k + 1个数分别是s, m, 则left必定在[s, m)之间
// 而有因为对start的取整,start必然等于s
return start
}
// 统计matrix中小于等于val的数的数目
func check(matrix [][]int, val int) int {
ans := 0
i, j := len(matrix) - 1, 0
for i >= 0 && j < len(matrix[0]) {
for i >= 0 && matrix[i][j] > val {
i --
}
if i < 0 {
break
}
ans = ans + i + 1
j ++
}
return ans
}
方法二:归并排序