diff --git a/Algorithms/378. Kth Smallest Element in a Sorted Matrix/378. Kth Smallest Element in a Sorted Matrix.go b/Algorithms/378. Kth Smallest Element in a Sorted Matrix/378. Kth Smallest Element in a Sorted Matrix.go new file mode 100644 index 00000000..529697c9 --- /dev/null +++ b/Algorithms/378. Kth Smallest Element in a Sorted Matrix/378. Kth Smallest Element in a Sorted Matrix.go @@ -0,0 +1,87 @@ +package leetcode + +import ( + "container/heap" +) + +// 解法一 二分搜索 +func kthSmallest378(matrix [][]int, k int) int { + m, n, low := len(matrix), len(matrix[0]), matrix[0][0] + high := matrix[m-1][n-1] + 1 + for low < high { + mid := low + (high-low)>>1 + // 如果 count 比 k 小,在大值的那一半继续二分搜索 + if counterKthSmall(m, n, mid, matrix) >= k { + high = mid + } else { + low = mid + 1 + } + } + return low +} + +func counterKthSmall(m, n, mid int, matrix [][]int) int { + count, j := 0, n-1 + // 每次循环统计比 mid 值小的元素个数 + for i := 0; i < m; i++ { + // 遍历每行中比 mid 小的元素的个数 + for j >= 0 && mid < matrix[i][j] { + j-- + } + count += j + 1 + } + return count +} + +// 解法二 优先队列 +func kthSmallest3781(matrix [][]int, k int) int { + if len(matrix) == 0 || len(matrix[0]) == 0 { + return 0 + } + pq := &pq{data: make([]interface{}, k)} + heap.Init(pq) + for i := 0; i < len(matrix); i++ { + for j := 0; j < len(matrix[0]); j++ { + if pq.Len() < k { + heap.Push(pq, matrix[i][j]) + } else if matrix[i][j] < pq.Head().(int) { + heap.Pop(pq) + heap.Push(pq, matrix[i][j]) + } else { + break + } + } + } + return heap.Pop(pq).(int) +} + +type pq struct { + data []interface{} + len int +} + +func (p *pq) Len() int { + return p.len +} + +func (p *pq) Less(a, b int) bool { + return p.data[a].(int) > p.data[b].(int) +} + +func (p *pq) Swap(a, b int) { + p.data[a], p.data[b] = p.data[b], p.data[a] +} + +func (p *pq) Push(o interface{}) { + p.data[p.len] = o + p.len++ +} + +func (p *pq) Head() interface{} { + return p.data[0] +} + +func (p *pq) Pop() interface{} { + p.len-- + return p.data[p.len] +} diff --git a/Algorithms/378. Kth Smallest Element in a Sorted Matrix/378. Kth Smallest Element in a Sorted Matrix_test.go b/Algorithms/378. Kth Smallest Element in a Sorted Matrix/378. Kth Smallest Element in a Sorted Matrix_test.go new file mode 100644 index 00000000..8019a021 --- /dev/null +++ b/Algorithms/378. Kth Smallest Element in a Sorted Matrix/378. Kth Smallest Element in a Sorted Matrix_test.go @@ -0,0 +1,48 @@ +package leetcode + +import ( + "fmt" + "testing" +) + +type question378 struct { + para378 + ans378 +} + +// para 是参数 +// one 代表第一个参数 +type para378 struct { + matrix [][]int + k int +} + +// ans 是答案 +// one 代表第一个答案 +type ans378 struct { + one int +} + +func Test_Problem378(t *testing.T) { + + qs := []question378{ + + question378{ + para378{[][]int{[]int{1, 5, 9}, []int{10, 11, 13}, []int{12, 13, 15}}, 8}, + ans378{13}, + }, + + question378{ + para378{[][]int{[]int{1, 5, 7}, []int{11, 12, 13}, []int{12, 13, 15}}, 3}, + ans378{9}, + }, + } + + fmt.Printf("------------------------Leetcode Problem 378------------------------\n") + + for _, q := range qs { + _, p := q.ans378, q.para378 + fmt.Printf("【input】:%v 【output】:%v\n", p, kthSmallest378(p.matrix, p.k)) + } + fmt.Printf("\n\n\n") +} diff --git a/Algorithms/378. Kth Smallest Element in a Sorted Matrix/README.md b/Algorithms/378. Kth Smallest Element in a Sorted Matrix/README.md new file mode 100755 index 00000000..a14e3380 --- /dev/null +++ b/Algorithms/378. Kth Smallest Element in a Sorted Matrix/README.md @@ -0,0 +1,40 @@ +# [378. Kth Smallest Element in a Sorted Matrix](https://leetcode.com/problems/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 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. + + +## 题目大意 + +给定一个 n x n 矩阵,其中每行和每列元素均按升序排序,找到矩阵中第 k 小的元素。请注意,它是排序后的第 k 小元素,而不是第 k 个元素。 + + +说明: +你可以假设 k 的值永远是有效的, 1 ≤ k ≤ n2 。 + + +## 解题思路 + + +- 给出一个行有序,列有序的矩阵(并非是按照下标有序的),要求找出这个矩阵中第 K 小的元素。注意找的第 K 小元素指的不是 k 个不同的元素,可能存在相同的元素。 +- 最容易想到的就解法是优先队列。依次把矩阵中的元素推入到优先队列中。维护一个最小堆,一旦优先队列里面的元素有 k 个了,就算找到结果了。 +- 这一题最优解法是二分搜索。那搜索的空间是什么呢?根据题意,可以知道,矩阵左上角的那个元素是最小的,右下角的元素是最大的。即矩阵第一个元素确定了下界,矩阵的最后一个元素确定了上界。在这个解空间里面二分搜索所有值,找到第 K 小的元素。判断是否找到的条件是,在矩阵中比 mid 小的元素个数等于 K。不断的逼近 low,使得 low == high 的时候,就是找到了第 K 小的元素了。(因为题目中说了,一定会存在第 K 小元素,所以二分搜索到一个元素的时候,一定会得出结果)。 + +![](https://img.halfrost.com/Leetcode/leetcode_378.png)