题目
题号:1
题目名:二维数组中的查找
题目描述
在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
初次思路
如果是有序数组,可以立马就想到二分查找
N行都是递增,那找到所在行,进行二分查找就行,在确定区间的时候也可以进一步优化
解题代码
public boolean Find(int target, int[][] array) {
/**
* 1.二位数组从左往右递增,从上往下递增,那么最小值在左上,最大值在左下
* 2.那么首先可以确定target所在区间,一维的左右端点决定了他的区间,如果超出最大值,说明false
* 3.二分查找找到当前行的位置,如果没有则输出false
*/
//非空校验
if (array == null || array[0].length == 0) {
return false;
}
//通过右端点找到每个线段右临界点
int row = array.length;//行长度
int col = array[0].length;//列长度
if(target>array[row-1][col-1]||target<array[0][0]) return false;
/**
* 从上往下遍历,如果这行满足这个数在这行区间,就继续遍历
*/
for (int i = 0; i < row; i++) {
//满足区间
if(array[i][0]<=target&&array[i][col-1]>=target) {
//进行二分查找
if(binarySearchTarget(array[i], 0, col - 1, target)) return true;
}else if(array[i][0]>=target) return false; //优化:左端点已经比数大了,没必要继续找了
}
return false;
}
private boolean binarySearchTarget(int[] arr, int start, int end, int target) {
while(start<=end) {
int mid = start+(end-start)/2;
if(arr[mid]>target) {
end = mid-1;
}else if(arr[mid]<target) {
start = mid+1;
}else return true;
}
return false;
}
时间复杂度为O(M*logN)
修改思路
可以根据其二维的递增性质,标定一个坐标后往另一侧进行搜索
解题代码
public boolean Find(int target, int[][] array) {
/**
* 1.二维数组从左往右递增,从上往下递增,右上角和左下角分别是行最小的最大值和列最大的最小值
* 2.可以向中心搜索到target
*/
//非空校验
if (array == null || array[0].length == 0) {
return false;
}
//通过右端点找到每个线段右临界点
int row = array.length;//行长度
int col = array[0].length;//列长度
if(target>array[row-1][col-1]||target<array[0][0]) return false;
/*
1.左下角往中心搜索
*/
//左下角坐标
int currR = row-1;
int currC = 0;
//行搜索边界值是0,列搜索边界值是col-1
while(currR>=0&&currC<col) {
if(array[currR][currC]==target) return true;
//如果这个值小于target,那么要往右搜索
else if(array[currR][currC]<target) currC++;
//否则往上搜索
else currR--;
}
return false;
}
这个时间复杂度是O(M+N)