题目描述:
在一个二维数组array中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
[
[1,2,8,9],
[2,4,9,12],
[4,7,10,13],
[6,8,11,15]]
给定 target = 7,返回 true。
给定 target = 3,返回 false。
数据范围:矩阵的长宽满足0≤n,m≤500 , 矩阵中的值满足0≤val≤10^9
进阶:空间复杂度 O(1),时间复杂度 O(n+m)
示例1:
输入:7,[[1,2,8,9],[2,4,9,12],[4,7,10,13],[6,8,11,15]]
返回值:true
说明:存在7,返回true
示例2:
输入:1,[[2]]
返回值:false
示例3:
输入:3,[[1,2,8,9],[2,4,9,12],[4,7,10,13],[6,8,11,15]]
返回值:false
说明:不存在3,返回false
解法一:遍历数组
思路:
利用双重for循环,直接遍历整个数组。
代码:
public class Solution {
public boolean Find(int target, int [][] array) {
//遍历数组
for(int i=0; i < array.length; i++){
for(int j=0; j < array[0].length; j++){
//如果当前元素值和target相等,即找到结果
if(array[i][j] == target){
return true;
}
}
}
//返回false
return false;
}
}
上述方法固然可以,但是很明显本题的考点并不是看你会不会for循环。在本题中,提到了:数组的每一行都按照从左到右升序排序,每一列都按照从上到下的递增顺序排序。因此,我们可以利用上述特点对数组进行遍历。由于行列递增,可以得出:在一列中的某个数字,其上的数字都比它小在一行中的某个数字,其右的数字都比它大。因此,整体搜索流程如下:
从数组左下角搜索(右上也可以,之所以不选择左上和右下,是因为左上位置的数字的右侧和下方位置数字都比它大,而右下的位置的数字的上方和左侧位置数字都比它小)
- 如果当前数字大于target,那么查找往上移一位
- 如果当前数字小于target,那么查找往右移一位。
- 查找到target,返回true; 如果越界或者没找到,返回false
代码:
public class Solution {
public boolean Find(int target, int [][] array) {
//如果数组长度为0,直接返回
if(array.length == 0){
return false;
}
int row = array.length - 1, col = 0;
//查找数组
while(row >= 0 && col < array[0].length){
if(array[row][col] == target){
return true;
}else if(array[row][col] > target){
row --;
}else{
col ++;
}
}
return false;
}
}
解法二:二分查找
思路:
把每一行看成一个有序的二维数组,利用二分查找找到target。
代码:
public class Solution {
public boolean Find(int target, int [][] array) {
if(array.length == 0){
return false;
}
for(int i=0; i < array.length; i++){
if(binSearch(array[i], 0, array[i].length-1, target)){
return true;
}
}
return false;
}
// 二分查找递归实现
public boolean binSearch(int srcArray[], int start, int end, int key) {
if(srcArray == null || srcArray.length == 0){
return false;
}
int mid = (end - start) / 2 + start;
if (srcArray[mid] == key) {
return true;
}
if (start >= end) {
return false;
} else if (key > srcArray[mid]) {
return binSearch(srcArray, mid + 1, end, key);
} else if (key < srcArray[mid]) {
return binSearch(srcArray, start, mid - 1, key);
}
return false;
}
}
另一种写法:
public class Solution {
public boolean Find(int target, int [][] array) {
int mid = 0;
for(int i = 0; i < array.length; i++){
int low = 0;
int high = array[0].length - 1;
while(low <= high){
mid = (low + high)/2;
if(target > array[i][mid]){
low = mid + 1;
}else if(target < array[i][mid]){
high = mid - 1;
}else{
return true;
}
}
}
return false;
}
}