剑指 Offer 04. 二维数组中的查找

119 阅读1分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第2天,点击查看活动详情

题目:现有一个n*m的二维数组,在二维数组中,每行的元素都按照从左到右递增的顺序排列,每一列都按照从上到下递增的顺序排序。现在有一个整数,其可能在这个二维数组中,也可能不在,要求设计一个高效的算法判断该整数是否在此数组中。

解题思路

本题和我们之前做的 LeetCode 240.搜索二维矩阵II 相同,此时复习一下,首先来看一个不高效的暴力解法,我们可以使用两层for循环来遍历二维矩阵,直接判断元素是否相等,可得代码如下:

public boolean findNumberIn2DArray(int[][] matrix, int target) {
    for(int i=0;i<matrix.length;i++){
        for(int j=0;j<matrix[0].length;j++){
            if(matrix[i][j] == target) return true;
        }
    }
    return false;
}

这种方式的时间复杂度为O(n2)O(n^2)

另一种思路是观察数组,数组的特性很明显,从左到右和从上到下都是有序的,那么我们从右向左以及从上往下看,是否可以发现从右上角来看,其左边的元素小于他而右边的元素大于他,也即构成了一颗二叉搜索树,那么我们此时的思路就是从数组的右上角进行判断,如果元素大于我们的目标值target则在此行向前找,如果小于target则在此列向下走,直到找到符合条件的值或者行或列超出索引即可,可得代码如下:

public boolean findNumberIn2DArray(int[][] matrix, int target) {
        if(matrix.length==0) return false;
        int columns = matrix[0].length;
        return NumberIn2DArray(matrix, 0, columns-1, target);
    }

    public boolean NumberIn2DArray(int[][] matrix, int row, int column, int target){
        if(row>matrix.length-1||column<0) return false;
        if(matrix[row][column]==target){
            return true;
        }else if(matrix[row][column]>target){
            return NumberIn2DArray(matrix, row, column-1, target);
        }else {
            return NumberIn2DArray(matrix, row+1, column, target);
        }
    }

这段代码时间复杂度为O(m+n)O(m+n),空间复杂度为O(m+n)O(m+n),因为用到了系统栈,我们可以对此代码进行优化,也即看LeetCode 240的解题思路,果然还是写不出来最好的解法~代码如下:

public boolean findNumberIn2DArray(int[][] matrix, int target) {
        if(matrix.length == 0) return false;
        int row = 0, column = matrix[0].length-1;
        while(row<matrix.length&&column>=0){
            if(matrix[row][column]==target){
                return true;
            }else if(matrix[row][column]>target){
                column--;
            }else {
                row++;
            }
        }
        return false;
    }

时间复杂度为O(m+n)O(m+n),空间复杂度为O(1)O(1)