題目:給定乙個 n x n 矩陣,其中每行和每列元素均按公升序排序,找到矩陣中第 k 小的元素
思路及演算法
由題目給出的性質可知,這個矩陣的每一行均為乙個有序陣列。問題即轉化為從這 n 個有序陣列中找第 k 大的數,可以想到利用歸併排序的做法,歸併到第 k 個數即可停止。
一般歸併排序是兩個陣列歸併,而本題是 n 個陣列歸併,所以需要用小根堆維護,以優化時間複雜度。
public
intkthsmallest2
(int
matrix,
int k)})
;int n = matrix.length;
for(
int i =
0; i < n; i++))
;}//維護最左側的一列最小值候選人,當有序佇列彈出7個最小值,此時佇列中的最小值即為所求
for(
int i =
0; i < k -
1; i++))
;}}return pq.
poll()
[0];
}
時間複雜度:o(klogn),歸併 k 次,每次堆中插入和彈出的操作時間複雜度均為logn。
空間複雜度:o(n),堆的大小始終為 n。
其實解決這個問題的關鍵,在於維護一組「最小值候選人」
在整個矩陣中,每次彈出矩陣中最小的值,第k個被彈出的就是我們需要的數字。
現在我們的目的很明確:每次彈出矩陣中最小的值。你需要保證最小值必然從這組候選人中產生,於是每次只要從候選人中彈出最小的乙個即可。
我們來選擇第一組候選人,在這裡可以選擇第一列,因為每乙個數字都是其對應行的最小值,全域性最小值也必然在其中。然後使用prorityqueue有序佇列來儲存這一組候選人,就能保證每次從佇列中彈出的都是候選人中的最小值。
例:選取以下矩陣,開始的候選人為第一列,然後每次選擇候選人中的最小值彈出,然後被彈出的那一行的候選人右移以為記得到該行新的候選人,當某一行的值彈完後將候選人佇列中長度減1即可,知道彈出第k-1個值,此時最小值佇列的值即為所求第k小的值。
步驟如下圖所示:
思路及演算法
由題目給出的性質可知,這個矩陣內的元素是從左上到右下遞增的(假設矩陣左上角為 matrix[0][0])。以下圖為例:
我們知道整個二維陣列中 matrix[0][0] 為最小值,matrix[n−1][n−1] 為最大值,現在我們將其分別記作 l 和 r。
可以發現乙個性質:任取乙個數 mid 滿足l≤mid≤r,那麼矩陣中不大於 mid 的數,肯定全部分布在矩陣的左上角。
例如下圖,取 mid=8:
我們可以看到,矩陣中大於 mid 的數就和不大於 mid 的數分別形成了兩個板塊,沿著一條鋸齒線將這個矩形分開。其中左上角板塊的大小即為矩陣中不大於 mid 的數的數量。
我們只要沿著這條鋸齒線走一遍即可計算出這兩個板塊的大小,也自然就統計出了這個矩陣中不大於mid 的數的個數了。
走法演示如下,依然取 mid=8:
可以這樣描述走法:
1、初始位置在 matrix[n−1][0](即左下角);
2、設當前位置為 matrix[i][j]。若 matrix[i][j]≤mid,則將當前所在列的不大於 mid 的數的數量(即 i+1)累加到答案中,並向右移動,否則向上移動;
3、不斷移動直到走出格仔為止。
我們發現這樣的走法時間複雜度為 o(n),即我們可以線性計算對於任意乙個 mid,矩陣中有多少數不大於它。這滿足了二分查詢的性質。
不妨假設答案為 x,那麼可以知道 l≤x≤r,這樣就確定了二分查詢的上下界。
每次對於「猜測」的答案 mid,計算矩陣中有多少數不大於mid:
如果數量不少於 k,那麼說明最終答案 x 不大於 mid;
如果數量少於 k,那麼說明最終答案 x 大於 mid。
這樣我們就可以計算出最終的結果 x 了。
public
intkthsmallest3
(int
matrix,
int k)
else
}return left;
}//判斷數量是否大於k
public
boolean
check
(int
matrix,
int mid,
int k,
int n)
else
}return num >= k;
}
時間複雜度:o(nlog(r−l)),二分查詢進行次數為 o(log(r−l)),每次操作時間複雜度為 o(n)。
空間複雜度:o(1)。
public
intkthsmallest
(int
matrix,
int k)
} arrays.
sort
(sorted)
;return sorted[k-1]
;}
時間複雜度:o(n^2logn),對 n^2個數排序。
空間複雜度:o(n^2),一維陣列需要儲存這 n^2個數。
暴力法容易理解,就是直接先把二維陣列轉換為一維陣列,然後對該一維陣列排序(呼叫arrays.sort()函式即可),然後排序後陣列中下標為k-1的值即為所求,但是這種方法沒有用到有序陣列的性質,而且新產生了乙個n*n的一維陣列,所以時間和空間複雜度都很高。
其它方法自行檢視leetcode官方題解。
參考:leetcode題解1
leecode官方題解
378 有序矩陣中第K小的元素
378.有序矩陣中第k小的元素 給定乙個n x n矩陣,其中每行和每列元素均按公升序排序,找到矩陣中第k小的元素。請注意,它是排序後的第k小元素,而不是第k個不同的元素。示例 matrix 1,5,9 10,11,13 12,13,15 k 8,返回 13。你可以假設 k 的值永遠是有效的,1 k ...
378 有序矩陣中第K小的元素
題目描述 給定乙個 n x n 矩陣,其中每行和每列元素均按公升序排序,找到矩陣中第 k 小的元素。請注意,它是排序後的第 k 小元素,而不是第 k 個不同的元素。示例 matrix 1,5,9 10,11,13 12,13,15 k 8,返回 13。你可以假設 k 的值永遠是有效的,1 k n2 ...
378 有序矩陣中第K小的元素
給定乙個n x n矩陣,其中每行和每列元素均按公升序排序,找到矩陣中第k小的元素。請注意,它是排序後的第k小元素,而不是第k個不同的元素。示例 matrix 1,5,9 10,11,13 12,13,15 k 8,返回 13。思路 在matrix 0 0 matrix length 1 length...