二分查找之二维矩阵

565 阅读2分钟

这是我参与2022首次更文挑战的第4天,活动详情查看:2022首次更文挑战

前言

  • 为了年后准备的目标,现在还是要多刷刷LeetCode滴 !-_-!

二分查找

  • 这次看了LeetCode上一道二分查找的算法题,题如下:
74. 搜索二维矩阵
编写一个高效的算法来判断 m x n 矩阵中,是否存在一个目标值。该矩阵具有如下特性:
    每行中的整数从左到右按升序排列。
    每行的第一个整数大于前一行的最后一个整数。

示例 1:
输入:matrix = [[1,3,5,7],[10,11,16,20],[23,30,34,60]], target = 3
输出:true

示例 2:
输入:matrix = [[1,3,5,7],[10,11,16,20],[23,30,34,60]], target = 13
输出:false
  • 根据题中给出的特性:每行数组中从左到右升序排列,而且每行的第一个整数大于前一行的最后一个整数。很明显解题思路可以按照二分查找进行解题。

解题方式一

  • 首先可以通过对二维数组进行二分查找,判断当前target在哪一列的数组。
  • 然后在对列上数组进行二分查找,进而找到具体值
  • 编码如下:
/**
 * 搜索二维矩阵
 * 编写一个高效的算法来判断m x n矩阵中,是否存在一个目标值。该矩阵具有如下特性:
 * 每行中的整数从左到右按升序排列。
 * 每行的第一个整数大于前一行的最后一个整数。
 *
 * @Author: ZRH
 * @Date: 2022/2/7 14:48
 */
public class Num74 {

    public static void main (String[] args) {

        int[][] matrix = new int[][]{{1, 3, 5, 7}, {10, 11, 16, 20}, {23, 30, 34, 60}};
        System.out.println(searchMatrix(matrix, 3));

        matrix = new int[][]{{1, 3, 5, 7}, {10, 11, 16, 20}, {23, 30, 34, 60}};
        System.out.println(searchMatrix(matrix, 13));

    }

    public static boolean searchMatrix (int[][] matrix, int target) {
        // 获取二维数组的宽、高
        int m = matrix.length - 1;
        int n = matrix[m].length - 1;
        // 首节点或尾节点判断
        if (matrix[0][0] > target || matrix[m][n] < target) {
            return false;
        }
        // 二分的左右边界、
        int l = 0, r = m, mid;
        while (l <= r) {
            // 对半取值
            mid = l + (r - l) / 2;
            // mid节点的数组边界判断
            if (matrix[mid][0] == target || matrix[mid][n] == target) {
                return true;
            }
            // target在当前二分的左边
            if (target < matrix[mid][0]) {
                // 右边节点往左移动
                r = mid - 1;
            } else {
                // target在当前二分的右边
                if (matrix[mid][n] >= target) {
                    // target在列数组上再次进行二分查找
                    int l1 = 0, r1 = n, mid1;
                    while (l1 <= r1) {
                        // 对半取值,并判断验证结果
                        mid1 = l1 + (r1 - l1) / 2;
                        if (matrix[mid][mid1] == target) {
                            return true;
                        }
                        if (target < matrix[mid][mid1]) {
                            // 右边节点往左移动
                            r1 = mid1 - 1;
                        } else {
                            // 左边节点往右移动
                            l1 = mid1 + 1;
                        }
                    }
                    return false;
                } else {
                    // 左边节点往右移动
                    l = mid + 1;
                }
            }
        }
        return false;
    }
}

---------------- 打印结果:
true
false

解题方式二

  • 从总体看整个二维数组从左到右,从上到下都是有序的。
  • 那么把当前行的数组头节点和上一行的数组尾结点进行拼接,最后就可以组成一个有序的数组,然后进行二分查找也是可以的。
  • 编码就不编码了,二分查找的思路大体都是一样。

最后

  • 虚心学习,共同进步-_-