young氏矩阵
http://www.jobcoding.com/array/matrix/young-tableau-problem/
如果一個矩陣每一行每一列都嚴格單調遞增,我們稱該矩陣為楊氏矩陣(Young Tableau)。對于楊氏矩陣(a[m][ n]),通常會涉及兩個問題:(1) 怎樣在楊氏矩陣中查找某個元素X?(2) 怎樣在楊氏矩陣找第k大的數?
2. 解決方案
楊氏矩陣是一種非常巧妙的數據結構,它既可以用來當堆,又可以用來當做平衡樹。
(1) 問題1求解
【方案一】
<二分查找>
對于楊氏矩陣,由于每行每列均是有序的,則可以于矩陣采用二分查找。具體方法是:
對于當前子矩陣a[i][j]~a[s][t],中間元素為a[(i+s)/2][(j+t)/2],如果a[(i+s)/2][(j+t)/2]==x,則找出該元素;如果a[(i+s)/2][(j+t)/2] > x,則在子矩陣a[i][j]~a[(i+s)/2][(j+t)/2]中查找;如果a[(i+s)/2][(j+t)/2] < x,則在三個子矩陣:a[i][(j+t)/2]~ a[(i+s)/2][t],a[(i+s)/2][(j+t)/2]~ a[s][t]和a[(i+s)/2][j]~ a[s][ (j+t)/2]中查找。該算法的遞歸式為f(mn)=3f(mn/4)+O(1),根據主定理知,時間復雜度為:O((mn)^(log4(3)))。
【方案二】
<類堆查找法>
楊氏矩陣具有明顯的堆特征:從矩陣的右上角出發(從左下角出發思路類似),對于元素a[i][j],如果a[i][j]==x,則找到元素x,直接返回;如果a[i][j] > x,則向下移動,即繼續比較a[i+1][j]與x;如果a[i][j]<x,則向左移動,即繼續比較a[i][j-1]與x。該算法的時間復雜度是O(m+n),代碼如下:
bool find_in_YoungTableau(int** a, int m, int n, int x) {assert(a != NULL && m > 0 && n > 0);int row, col;row = 0;col = n-1;while(row <= m-1 && col >= 0) {if(a[row][col] == x)return true;else if(a[row][col] > x)col--;elserow++;}return false; }(2) 問題2求解
【方案一】
<小頂堆法>
首先將a[0][0]加入小頂堆,然后每次從小頂堆中取出最小元素,并加入比該元素大且與之相鄰的兩個元素(對于a[0][0],則需要加入a[0][1]和a[1][0]),直到取出第k個元素,需要注意的是,需要采用額外空間記錄某個元素是否已經加入到小頂堆以防止重復加入。
【方案二】
<二分枚舉+類堆查找>
首先,二分枚舉找到一個數x,它比楊氏矩陣中k個數大;然后,利用類堆查找法找到剛好小于x的元素。該算法的時間復雜度為O((m+n)lg(mn)),但不需要額外存儲空間。代碼如下:
總結