algorithm-reading

Search a 2D Matrix

Source

Write an efficient algorithm that searches for a value in an m x n matrix.

This matrix has the following properties:

    * Integers in each row are sorted from left to right.

    * The first integer of each row is greater than the last integer of the previous row.

Example
Consider the following matrix:

[

    [1, 3, 5, 7],

    [10, 11, 16, 20],

    [23, 30, 34, 50]

]

Given target = 3, return true.

Challenge
O(log(n) + log(m)) time

题解 - 一次二分搜索 V.S. 两次二分搜索

一次二分搜索

由于矩阵按升序排列,因此可将二维矩阵转换为一维问题。对原始的二分搜索进行适当改变即可(求行和列)。时间复杂度为 O(log(mn))=O(log(m)+log(n))O(log(mn))=O(log(m)+log(n))

两次二分搜索

先按行再按列进行搜索,即两次二分搜索。时间复杂度相同。

以一次二分搜素的方法为例。

Java

/**
 * 本代码由九章算法编辑提供。没有版权欢迎转发。
 * http://www.jiuzhang.com/solutions/search-a-2d-matrix
 */
// Binary Search Once
public class Solution {
    public boolean searchMatrix(int[][] matrix, int target) {
        if (matrix == null || matrix.length == 0) {
            return false;
        }
        if (matrix[0] == null || matrix[0].length == 0) {
            return false;
        }

        int row = matrix.length, column = matrix[0].length;
        int start = 0, end = row * column - 1;
        int mid, number;

        while (start + 1 < end) {
            mid = start + (end - start) / 2;
            number = matrix[mid / column][mid % column];
            if (number == target) {
                return true;
            } else if (number < target) {
                start = mid;
            } else {
                end = mid;
            }
        }

        if (matrix[start / column][start % column] == target) {
            return true;
        } else if (matrix[end / column][end % column] == target) {
            return true;
        }

        return false;
    }
}

源码分析

仍然可以使用经典的二分搜索模板,注意下标的赋值即可。

  1. 首先对输入做异常处理,不仅要考虑到matrix为空串,还要考虑到matrix[0]也为空串。
  2. 如果搜索结束时target与start或者end的值均不等时,则必在矩阵的值范围之外,避免了特殊情况的考虑。

第一次A掉这个题用的是分行分列两次搜索,好蠢...