378.序矩阵中第 K 小的元素

87 阅读1分钟

题目:
给你一个 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
}

方法二:归并排序