每日一题算法-搜索二维矩阵

题目

编写一个高效的算法来搜索 m x n 矩阵 matrix 中的一个目标值 target。该矩阵具有以下特性:

每行的元素从左到右升序排列。
每列的元素从上到下升序排列。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/search-a-2d-matrix-ii
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

解法

方法一:暴力法
对于每一行我们可以像搜索未排序的一维数组——通过检查每个元素来判断是否有目标值。
算法:
这个算法并没有做到聪明的事情。我们循环数组,依次检查每个元素。如果,我们找到了,我们返回 true。否则,对于搜索到末尾都没有返回的循环,我们返回 false。此算法在所有情况下都是正确的答案,因为我们耗尽了整个搜索空间。

class Solution {
    public boolean searchMatrix(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(m)O(m)O(m)或O(n)O(n)O(n)元素。
算法:
首先,我们初始化一个指向矩阵左下角的 (row,col)(row,col)(row,col) 指针。然后,直到找到目标并返回 true(或者指针指向矩阵维度之外的 (row,col)(row,col)(row,col) 为止,我们执行以下操作:如果当前指向的值大于目标值,则可以 “向上” 移动一行。 否则,如果当前指向的值小于目标值,则可以移动一列。不难理解为什么这样做永远不会删减正确的答案;因为行是从左到右排序的,所以我们知道当前值右侧的每个值都较大。 因此,如果当前值已经大于目标值,我们知道它右边的每个值会比较大。也可以对列进行非常类似的论证,因此这种搜索方式将始终在矩阵中找到目标(如果存在)。

class Solution {
    public boolean searchMatrix(int[][] matrix, int target) {
        // start our "pointer" in the bottom-left
        int row = matrix.length-1;
        int col = 0;

        while (row >= 0 && col < matrix[0].length) {
            if (matrix[row][col] > target) {
                row--;
            } else if (matrix[row][col] < target) {
                col++;
            } else { // found it
                return true;
            }
        }

        return false;
    }
}

复杂度分析

时间复杂度:O(n+m)O(n+m)O(n+m)。
时间复杂度分析的关键是注意到在每次迭代(我们不返回 true)时,行或列都会精确地递减/递增一次。由于行只能减少 mmm 次,而列只能增加 nnn 次,因此在导致 while 循环终止之前,循环不能运行超过 n+mn+mn+m 次。因为所有其他的工作都是常数,所以总的时间复杂度在矩阵维数之和中是线性的。
空间复杂度:O(1)O(1)O(1),因为这种方法只处理几个指针,所以它的内存占用是恒定的。

你可能感兴趣的:(每日一题算法-搜索二维矩阵)