http://www.jobcoding.com/array/matrix/young-tableau-problem/
2. 解决方案
杨氏矩阵是一种非常巧妙的数据结构,它既可以用来当堆,又可以用来当做平衡树。
对于杨氏矩阵,由于每行每列均是有序的,则可以于矩阵采用二分查找。具体方法是:
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--;
else
row++;
}
return false;
}
首先,二分枚举找到一个数x,它比杨氏矩阵中k个数大;然后,利用类堆查找法找到刚好小于x的元素。该算法的时间复杂度为O((m+n)lg(mn)),但不需要额外存储空间。代码如下:
int find_kth_in_YoungTableau(int** a, int m, int n, int k) {
int low = a[0][0];
int high = a[m-1][n-1];
int order = 0;
int mid = 0;
do {
mid = (low + high) >> 1;
order = get_order(a, m, n, mid);
if(order == k)
break;
else if(order > k)
high = mid - 1;
else
low = mid + 1;
} while(1); //二分枚举整,找出正好大于k的一个整数 mid
int row = 0;
int col = n - 1;
int ret = mid;
while(row <= m-1 && col >= 0) { //找出比mid小的最大数
if(a[row][col] < mid) {
ret = (a[row][col] > ret) ? a[row][col] : ret;
row++;
} else {
col--;
}
}
return ret;
}
//整数k在矩阵中的排名
int get_order(int** a, int m, int n, int k) {
int row, col, order;
row = 0;
col = n-1;
order = 0;
while(row <= m-1 && col >= 0) {
if(a[row][col] < k) {
order += col + 1;
row++;
} else {
col--;
}
}
return order;
}