题目
二维数组中的查找
在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
例如:
1,2,5
3,4,9
7,8,21
3*3的数组
解答
思路
从二维数组的右上角的元素开始判断,因为此元素是它所在行的最大数,是它所在的列的最小数。如果它等于要查找的数字,则查找过程结束。如果它大于要查找的数字,则可以排除它所在的列。如果它小于要查找的数字,则可排除它所在的行。这样如果要查找的数字不在数组的右上角,则每次判断都可以排除一行或一列以缩小查找范围,直到找到要查找的数字,或者查找范围为空。
代码
Java代码实现
public boolean findNum(int [][] array,int target) {
if(array == null || array.length==0 ||array[0].length==0){
return false;
}
int rowLen = array.length; // 行数
int columnLen = array[0].length; // 列数
if(target < array[0][0] || target > array[rowLen-1][columnLen-1]){
return false;
}
int i = 0;
int j = columnLen-1;
while(i<rowLen && j>=0){
if(array[i][j] == target){
return true;
}else if(array[i][j] > target){
j--;
}else{
i++;
}
}
return false;
}
扩展
若是在上题中加入一个条件:每行的首数大于上行的尾数
例如:
1,2,3
4,5,6
7,8,9
3*3的数组
思路
对于排好序的数组考虑使用二分查找法,可以得到O(logn)的查找效率。那么这个二维数组其实可以看作一维有序数组,在这个一维数组中,元素被分为m段,每段固定长度。即要将此二维数组映射到一个一维数组。
假设映射到一维数组A,A有m*n个元素,那么A[k]=matrix[i][j], 当k=*n+j,即i=k/n, j=k%n。有了映射关系后就可以堆展开之后的一维数组进行二分查找,时间复杂度为O(log(m*n))。
代码
Java代码实现
public boolean findNumEx(int [][] array,int target) {
if(array == null || array.length==0 || array[0].length==0){
return false;
}
int rowLen = array.length;
int columnLen = array[0].length;
if(target < array[0][0] || target > array[rowLen-1][columnLen-1]){
return false;
}
int low = 0;
// 总共有rowLen*columnLen个元素
int high = rowLen*columnLen-1;
while(low <= high){
int mid = (low + high)/2;
if(array[mid/columnLen][mid%columnLen] == target){
// 找到此元素,返回true
return true;
}else if(array[mid/columnLen][mid%columnLen] < target){
// 在右半部分继续找
low = mid+1;
}else{
// 在右半部分继续找
high = mid-1;
}
}
return false;
}