Search a 2D Matrix

https://leetcode.com/problems/search-a-2d-matrix/

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.

 

For example,

Consider the following matrix:

[

  [1,   3,  5,  7],

  [10, 11, 16, 20],

  [23, 30, 34, 50]

]

Given target = 3, return true.

解题思路:

这道题属于常规思路,两次二分查找。首先二分查找应该在的行,然后再在该行内做一次标准的二分查找。

如果matrix[mid][0] > target,说明要找的数比mid行第一个数小,那么一定在mid行以前。如果matrix[mid][0] < target,说明target比mid行第一个数字大,那么有可能就在mid行,也有可能在mid行往后的行。

这时就通过对比mid行最后一个数字和target的大小来判断。

public class Solution {

    public boolean searchMatrix(int[][] matrix, int target) {

        int start = 0;

        int end = matrix.length - 1;

        int row = -1;

        

        while(start <= end){

            int mid = (start + end) / 2;

            if(matrix[mid][0] == target){

                return true;

            }

            if(matrix[mid][0] > target){

                end = mid - 1;

            }

            if(matrix[mid][0] < target){

                if(matrix[mid][matrix[mid].length - 1] == target){

                    return true;

                }

                if(matrix[mid][matrix[mid].length - 1] > target){

                    row = mid;

                    break;

                }

                if(matrix[mid][matrix[mid].length - 1] < target){

                    start = mid + 1;

                }

            }

        }

        if(row == -1){

            return false;

        }

        

        start = 0;

        end = matrix[row].length - 1;

        while(start <= end){

            int mid = (start + end) / 2;

            if(matrix[row][mid] == target){

                return true;

            }

            if(matrix[row][mid] < target){

                start = mid + 1;

            }

            if(matrix[row][mid] > target){

                end = mid - 1;

            }

        }

        return false;

    }

}

 后来看到网友在第一次二分搜索,即搜索行的时候,有比较简洁,但需要理解一下的方法。就是直接用end作为最后的行。我们看看如何证明?

假设有行4、22、35、47、89、100、120,我们想找90,应该在89那一行。第一次mid=47,于是start到了89那一行。然后mid=100,于是end=89。这时start=end=89。要找90,start++,到了100。循环退出。

可以看到end正好在要找的那一行,而start则超过了一行。

为什么会这样?因为end是当target<mid的时候更新的,如果target存在,最后一次搜索一定是start=end=mid落在target所在行,target只可能>mid,所以只会更新start++。这样最终end一定在target所在的行上,除非end减到最后已经为-1了。

public class Solution {

    public boolean searchMatrix(int[][] matrix, int target) {

        int start = 0;

        int end = matrix.length - 1;

        int row = -1;

        

        while(start <= end){

            int mid = (start + end) / 2;

            if(matrix[mid][0] == target){

                return true;

            }

            if(matrix[mid][0] > target){

                end = mid - 1;

            }

            if(matrix[mid][0] < target){

                start = mid + 1;

            }

        }

        

        row = end;

        if(row == -1){

            return false;

        }

        

        start = 0;

        end = matrix[0].length - 1;

        while(start <= end){

            int mid = (start + end) / 2;

            if(matrix[row][mid] == target){

                return true;

            }

            if(matrix[row][mid] < target){

                start = mid + 1;

            }

            if(matrix[row][mid] > target){

                end = mid - 1;

            }

        }

        return false;

    }

}

这道题本身不难,但是对理解二分查找的过程,特别是两端指针更新的条件和结果,循环的过程,还是比较好的。

你可能感兴趣的:(search)