在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。
请完成一个函数,输入这样的一个二维数组和一个整数.返回在二维数组是否包含此数字.
例如下面的二维数组就是每行、每列都递增排序。如果在这个数组中查找数字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(@"没找到");
}