在一個二維數組中,每一行都按照從左到右遞增的順序排序,每一列都按照從上到下遞增的順序排序。
請完成一個函數,輸入這樣的一個二維數組和一個整數.返回在二維數組是否包含此數字.
例如下面的二維數組就是每行、每列都遞增排序。如果在這個數組中查找數字7,則返回true;
如果査找數字5,由於數組不含有該數字,則返回false。
1 2 8 9
2 4 9 12
4 7 10 13
6 8 11 15
最簡單,也是最不得分的思路,遍歷唄,如果是a[n][m], 那麼時間複雜度就是O(n*m),
- (void)fun1 {
const int section = 4;
const int row = 4;
int a[section][row] ={
{1,2,8,9},
{2,3,9,12},
{4,7,10,13},
{6,8,11,15},
};
// 找出7
int result = 7;
for (int i = 0; i<section; i++) {
for (int j=0; j<row; j++) {
if (a[i][j] == result) {
NSLog(@"找到了 在%d行 第%d列",i,j);
break;
}
}
}
NSLog(@"沒找到");
}
在上面的基礎上開始優化, 可以對每一行或者每一列進行優化,來一個二分查找,可以降低時間複雜度,這樣的話就是O(nlogm)或者O(mlogn),
- (void)fun1 {
const int section = 4;
const int row = 4;
int a[section][row] ={
{1,2,8,9},
{2,3,9,12},
{4,7,10,13},
{6,8,11,15},
};
// 找出7
int result = 7;
for (int i = 0; i<section; i++) {
int line = findIn(a[i], row, result);
if (line>0) {
NSLog(@"找到了 在%d %d",i,line);
}
}
NSLog(@"沒找到");
}
// 二分查找,在長度爲count的有序遞增array中查找num,返回下標,-1表示沒有這個num
int findIn(int array[],int count,int num) {
if (count<=0 || array == NULL) {
NSLog(@"不合法");
return -1;
}
int begin = 0;
int end = count-1;
while (begin<=end) {
// 最小數>num,這個數不存在
if (array[begin]>num) {
break;
}
// 最大數<num,這個數不存在
if (array[end]<num) {
break;
}
// 說明在begin和end中間,二分查找
int mid = (begin+end)/2;
if (array[mid] > num) {
end = mid-1;
} else if (array[mid] < num) {
begin = mid+1;
} else if (array[mid] == num) {
NSLog(@"找到了 %d在下標爲%d的位置",num,mid);
return mid;
}
}
NSLog(@"沒找到%d",num);
return -1;
}
這個是看了劍指offer中的做法, 選取右上角,左下角都可以,但是左上角和右下角是不可以的.
首先選取數組中右上角的數字。
- 如果該數字等於要查找的數字,查找過程結束;
- 如果該數字大於要査找的數字,剔除這個數字所在的列;
- 如果該數字小於要查找的數字,剔除這個數字所在的行。
也就是說如果要查找的數字不在數組的右上角,則每一次都在數組的查找範圍中別除一行或者一列,這樣每一步都可以縮小査找的範圍,直到找到要査找的數字,或者查找範圍爲空。一次比較可以處理一行或者一列,整體下來,時間複雜度是O(n+m), 時間複雜度已經到線性級別了.
這樣一條線也是單調遞增的,所以右上角這個位置可以一次處理一行或者一列數據.
- (void)fun1 {
const int section = 4;
const int row = 4;
int a[section][row] ={
{1,2,8,9},
{2,3,9,12},
{4,7,10,13},
{6,8,11,15},
};
// 找出7
int result = 7;
// 從右上角開始
int i = 0;
int j = row-1;
while (i<section && j>=0) {
// 取右上角的數字
// 右上角>result,說明這一列是不會有了,j--
if (a[i][j] > result) {
j--;
// 右上角<result,說明這一行是不會有了,i++
} else if(a[i][j] < result) {
i++;
}else {
NSLog(@"找到了 在(%d,%d)位置",i,j);
return;
}
}
/*
// 從左下角開始
int i = section-1;
int j = 0;
while (i>=0 && j<row) {
// 取左下角的數字
// 左下角>result,說明這一行是不會有了,i--
if (a[i][j] > result) {
i--;
// 左下角<result,說明這一列是不會有了,j++
} else if(a[i][j] < result) {
j++;
}else {
NSLog(@"找到了 在a[%d][%d]位置",i,j);
return;
}
}
*/
NSLog(@"沒找到");
}