剑指offer 4:二维数组中的查找

题目描述:

在一个二维数组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;
    }
}

猜你喜欢

转载自blog.csdn.net/weixin_47382783/article/details/121347809