【从心开始刷leetcode – 21】240. 搜索二维矩阵 II

题目

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

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

示例 1:

输入: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

示例 2:

输入: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 = 20
输出:false

提示:

  • m == matrix.length
  • n == matrix[i].length
  • 1 <= n, m <= 300
  • -109 <= matrix[i][j] <= 109
  • 每行的所有元素从左到右升序排列
  • 每列的所有元素从上到下升序排列
  • -109 <= target <= 109

题解

解法一 缩减数组

通过遍历最后一行和最后一列,找到第一个比target值大的那一行/列,从而缩减了数组

class Solution {
    public boolean searchMatrix(int[][] matrix, int target) {
        int m = matrix.length, n = matrix[0].length;
        if (matrix[m - 1][n - 1] < target || matrix[0][0] > target) return false;
        // 1. 遍历找到最后一个元素大于目标值的列 从这一列开始 缩减了目标矩阵
        int begin_row = 0, begin_line = 0;
        
        for (int i = 0; i < m; i++) {
            if (matrix[i][n - 1] == target) {
                return true;
            } else if (matrix[i][n - 1] > target) {
                begin_row = i;
                break;
            }
        }
        for (int i = 0; i < n; i++) {
            if (matrix[m - 1][i] == target) {
                return true;
            } else if (matrix[m - 1][i] > target) {
                begin_line = i;
                break;
            }
        }
        // ==== 找到了缩减后的矩阵,开始遍历
        for (int i = begin_row; i < m; i++)
            for (int j = begin_line; j < n; j++)
                if (matrix[i][j] == target) return true;
        return false;

    }
}

解法二 二分查找

因为每一行每一列都是有序的,可以直接对每一行二分查找

class Solution {
    public boolean searchMatrix(int[][] matrix, int target) {
        for (int[] row : matrix) {
            int index = search(row, target);
            if (index >= 0) {
                return true;
            }
        }
        return false;
    }

    public int search(int[] nums, int target) {
        int low = 0, high = nums.length - 1;
        while (low <= high) {
            int mid = (high - low) / 2 + low;
            int num = nums[mid];
            if (num == target) {
                return mid;
            } else if (num > target) {
                high = mid - 1;
            } else {
                low = mid + 1;
            }
        }
        return -1;
    }
}

时间复杂度O(MlogN)

解法三 最优解法 Z字查找

以matrix的右上角为起点,这个点有这样的特征:

  • 是该行中最大的元素
  • 是该列中最小的元素

因此判断目标值与这个元素的大小

  • 如果该点(右上角)大于target,说明不可能在这一列中(该点所在列都大于该点),把这一列直接去掉(让该点左移)
class Solution {
    public boolean searchMatrix(int[][] matrix, int target) {
        int ponit_row = 0, ponit_line = matrix[0].length - 1;
        while (ponit_line >= 0 && ponit_row < matrix.length) {
            if (matrix[ponit_row][ponit_line] > target) {
                ponit_line--;
            } else if (matrix[ponit_row][ponit_line] < target) {
                ponit_row++;
            } else {
                return true;
            }
        }
        return false;
    }
}

时间复杂度:O(M+N)

小结

今天这道题的重点是找到起始点右上角点

这几天的矩阵类型的题目大致有这几类:

  1. 对矩阵的原地操作 : 这一类题的重点在于如何在不影响后续操作的前提上对行/列进行原地标记
  2. 在矩阵中的螺旋遍历
  3. 对矩阵进行空间翻转
  4. 对矩阵进行缩减
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇