# Leetcode 解題速記 378. Kth Smallest Element in a Sorted Matrix
###### tags: `LeetCode` `C++`
題敘:
---
Given an `n x n matrix` where each of the rows and columns is sorted in ascending order, return the `kth` smallest element in the matrix.
Note that it is the `kth` smallest element in the sorted order, not the `kth` distinct element.
You must find a solution with a memory complexity better than `O(n^2)`.
Example 1:
```cpp
Input: matrix = [[1,5,9],[10,11,13],[12,13,15]], k = 8
Output: 13
Explanation: The elements in the matrix are [1,5,9,10,11,12,13,13,15], and the 8th smallest number is 13
```
Example 2:
```cpp
Input: matrix = [[-5]], k = 1
Output: -5
```
測資範圍:
---
* `n == matrix.length == matrix[i].length`
* `1 <= n <= 300`
* `-109 <= matrix[i][j] <= 109`
* `All the rows and columns of matrix are guaranteed to be sorted in non-decreasing order.`
* `1 <= k <= n2`
解題筆記:
---
### 1. Binary Search
此題binary search的目標直接是答案本身。
首先,設定lower bound為`matrix[0][0]`,upper bound為`matrix.back().back()`,middle為`floor(Upper+lower)/2`。目標是統計matrix中有多少數字少於middle,計為count,當count < k時將lower bound提升到middle + 1,反之降低upper bound為middle。
如何取得count的數量呢?根據題目敘述,我們可以知道matrix中的元素以遞增的方式排序。根據這個特性,我們先找到小於M的`matrix[i][j]`,此時我們知道有j個數字小於M,因此對於i+1排我們也知道最少有j個數字小於M。因此,我們可以直接從matrix[i+1][j]開始,不用從頭開始計算,由此節省計算時間。
### 2. Priority Queue
對於這種需要排序且找特定位置元素的題目,使用priority queue也是不錯的選擇,解法相對binary search也單純許多。
我們利用priority queue會自動將元素由大到小排序的特性,只需要將matrix中的數字一一push進去,然後將priority queue的大小限制在題目要求的k個元素,只要超過k就pop掉目前最大的元素。
之後只要將整個matrix都traverse過一次後就可以在priority queue中保留k個由大到小的數字,此時queue中最大的元素便是我們題目要求的答案。
程式碼:
---
### 1. Binary Search
``` cpp
class Solution {
public:
int kthSmallest(vector<vector<int>>& matrix, int k) {
int length = matrix.size(), lower = matrix[0][0], upper = matrix.back().back(), middle, lessThan;
while (lower < upper)
{
middle = (lower + upper) >> 1;
lessThan = 0;
for (int i = 0, j = length - 1; i < length; ++i)
{
while (j >= 0 && middle < matrix[i][j])
--j;
lessThan += j + 1;
}
if (lessThan < k)
lower = middle + 1;
else
upper = middle;
}
return lower;
}
};
```
### 2. Priority Queue
```cpp
class Solution {
public:
int kthSmallest(vector<vector<int>>& matrix, int k) {
priority_queue<int> pq;
int n = matrix.size();
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
pq.push(matrix[i][j]);
if (pq.size() > k)
{
pq.pop();
}
}
}
return pq.top();
}
};
```