剑指offer 04 二维数组的查找

剑指offer 04 二维数组的查找

题目:

在一个 n * m 的二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。

示例:

现有矩阵 matrix 如下:

[
  [1,   4,  7, 11, 15],
  [2,   5,  8, 12, 19],
  [3,   6,  9, 16, 22],
  [10, 13, 14, 17, 24],
  [18, 21, 23, 26, 30]
]

给定 target = 5,返回 true。

给定 target = 20,返回 false。

限制:

0 <= n <= 1000

0 <= m <= 1000

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/er-wei-shu-zu-zhong-de-cha-zhao-lcof

解析

PS: 题目有个坑 n , m 是可以=0的,此时可以直接返回false,因为数组没有任何一个元素

方法一、暴力

普通的暴力遍历解法就不赘述了

复杂度分析:

  • 时间复杂度:O(nm)。二维数组中的每个元素都被遍历,因此时间复杂度为二维数组的大小。
  • 空间复杂度:O(1)

方法二、线性查找

利用 每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序 的规律

target与第一行的最后一个元素end比较

  1. 如果target>end,说明target大于这一行的所有元素,continue到下一行比较最后一个元素

  2. 如果target<end, 说明可能在end前面找到相等的元素,则左移一列

  3. 如果target==endreturn true

可以证明,如果直到最后一行还不能找到target==end则说明二维数组没有target

public class Offer04 {
    public static boolean findNumberIn2DArray(int[][] matrix, int target) {
        // 数组没有元素直接 return false
        if (matrix.length == 0 || matrix[0].length == 0) {
            return false;
        }
        int r = matrix.length - 1;
        int c = matrix[0].length - 1;
        for (int i = 0; i <= r; i++) {                // 从第一行开始
            int end = matrix[i][c];
            if (target == end) {
                return true;
            } else if (target > end) {
                continue;                              // target > end 下移一行
            } else if (target < end) {
                for (int j = c - 1; j >= 0; j--) {     // target < end 左移一列
                    if (matrix[i][j] == target) {
                        return true;
                    } else if (matrix[i][j] < target) {
                        break;                         // 提前结束列遍历
                    }
                }
            }
        }
        return false;
    }

    public static void main(String[] args) {
        // 测试用例
        int[][] arr = {{1, 4, 7, 11, 15},
                {2, 5, 8, 12, 19},
                {3, 6, 9, 16, 22},
                {10, 13, 14, 17, 24},
                {18, 21, 23, 26, 30}};
        System.out.println(findNumberIn2DArray(arr, 5));  // true
        System.out.println(findNumberIn2DArray(arr, 20)); // false

    }
}

复杂度分析

  • 时间复杂度:O(n+m)。访问到的下标的行最多增加 n 次,列最多减少 m 次,因此循环体最多执行 n + m 次。这种方法查找的时间复杂度是线性的,所以称为线性查找

  • 空间复杂度:O(1)。

posted @ 2020-10-12 17:08  cangjian  阅读(53)  评论(0)    收藏  举报