在某个矩阵中,每行元素是递增的,每列元素也是递增的。即a[i][j]<a[i+1][j]且a[i][j]<a[i][j+1]。例如下列矩阵:
4 7 11 15
5 8 12 19
6 9 16 22
13 14 17 24
21 23 26 30,这便是一个杨氏矩阵。
要在这样的矩阵中查找某个数值元素的位置,或者判断某个数值在不在这个矩阵中。
1.线性法。每次都找最右上角的元素,如果要查找数字(target)大于右上角的数字,则向下移动(删除右上方元素所在一行),若要查找数字(target)小于右上角的数字,则向左移动(删除右上方元素所在一列),要在上述矩阵中查找21,首先21与15比较,21>15,因此删除第一行,右上方的元素变为19,21>19,删除19所在的第二行,右上方元素变为22,21<22,删除22所在的一列,右上方元素变为16,21>16,删除16所在的一行,右上方元素变为17,21>17,删除17所在的一行,右上角元素变为26,21<26,删除26所在的一列,右上角元素变为23,21<23,删除23所在的一列,右上方元素变为21,成功!如下图所示:
//杨氏查找线性搜索算法 #include<iostream> #include<vector> #define max 100 using namespace std; vector<int> Young1(int array[][4],int row,int col,int target) { vector<int> v; int begin_row = 0; int begin_col = col-1; if(target < array[0][0] || target > array[row-1][col-1]) { v.push_back(-1); v.push_back(-1); return v; } while(begin_row < row && begin_col >= 0) { if(target > array[begin_row][begin_col]) begin_row ++; else if(target < array[begin_row][begin_col]) begin_col --; else { v.push_back(begin_row); v.push_back(begin_col); return v; } } v.push_back(-1); v.push_back(-1); return v; } int main(void) { int array[5][4]={4,7,11,15,5,8,12,19,6,9,16,22,13,14,17,24,21,23,26,30}; vector<int> result = Young1(array,5,4,21); for(vector<int>::iterator it = result.begin();it != result.end();it ++) { cout<<*it<<endl; } system("pause"); return 0; }
最坏时间复杂度O(N+M)。线性时间内完成。
2.分治法。首先以矩阵中间元素为中心将矩阵分为四部分,下图为例,以⑨为中心分为红色1,2,3,4部分,如果查找的元素大于9,例如查找21,因为1号区域内部的元素全部小于9,因此只需要在2,3,4区域内部查找即可;如果查找的元素小于9,4号区域内部的元素全部大于9,因此只需要在1,2,3区域内部查找即可。
#include<iostream> #define max 100 using namespace std; /* row,col--行数,列数 lr lc矩阵左上角坐标 rr rc矩阵右上角坐标 target 要查找的数 result_row ,result_col 目标坐标 */ bool Young2(int array[][4],int row,int col,int target,int lr,int lc,int rr,int rc,int &result_row,int &result_col) { if(lr>rr||lc>rc) { result_row = -1; result_col = -1; return false; } if(target < array[lr][lc] || target > array[rr][rc]) { result_row = -1; result_col = -1; return false; } int begin_row_index = (int)((lr+rr)/2); int begin_col_index = (int)((lc+rc)/2); if(array[begin_row_index][begin_col_index]==target) { result_row = begin_row_index; result_col = begin_col_index; return true; } else if(array[begin_row_index][begin_col_index] < target) { return Young2(array,row,col,target,begin_row_index+1,begin_col_index+1,rr,rc,result_row,result_col)//4号区域 ||Young2(array,row,col,target,lr,begin_col_index+1,begin_row_index,rc,result_row,result_col)//2 ||Young2(array,row,col,target,begin_row_index+1,lc,rr,begin_col_index,result_row,result_col);//3 } else { return Young2(array,row,col,target,lr,lc,begin_row_index,begin_col_index,result_row,result_col)//1 ||Young2(array,row,col,target,lr,begin_col_index+1,begin_row_index,rc,result_row,result_col)//2 ||Young2(array,row,col,target,begin_row_index+1,lc,rr,begin_col_index,result_row,result_col);//3 } } int main(void) { int array[5][4]={4,7,11,15,5,8,12,19,6,9,16,22,13,14,17,24,21,23,26,30}; int a,b; bool r = Young2(array,5,4,21,0,0,4,3,a,b); cout<<r<<","<<a<<";"<<b<<endl; system("pause"); return 0; }