LeetCode 74. 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.

题解:

可以当成一个一维矩阵来处理,但是本题的难点就是如何将2D矩阵m*n 转换成1D,然后利用二分查找法来解决问题。

转换的重点就在于每个点的位置,在矩阵表示中,我们习惯用(i,j)来表示一个点,这里用所以这就有碍于我们使用(mid/n, mid%n) 来表示。

举例,像题中的例子我可以将其转化为:

position: 0   1   2   3   4   5   6   7   8   9   10   11   

values:   1   3   5   7   10 11 16 20  23 30  34  50

row:       0   0   0   0   1   1   1   1   2   2    2    2

column:  0   1   2   3   0   1   2   3   0   1    2    3 

其中:行数m=3,列数n=4

如上,这个就是将2D矩阵转化成1行数组的对应表。所以对于二分查找法的初始值为: low=0, high=m*n-1(总共数值的个数,因为从0开始所以减1). 而为了能够方便在given 2D matrix找到需要比对的值,我们还是需要确定行数和列数,通过上表可以看出,行数是position/n, 而列数是position%n, 这样一来,就能很容易的在原矩阵中定位到所需要的值。剩下其他的解题思路,就与二分查找法一模一样了。 

Time Complexity: O(log(m*n)), 因为二分法查找的总数是m*n.

Space: O(1).

第二种方法是进行两次二分法查找,第一次找行,第二次找列.

Note: 方法二中,跳出找行的loop后, r 肯定指向开始元素比target小的行, l肯定指向开始元素比target大的行,所以row应该选r. 

并且找注意r 有可能为-1. 这是corner case 若是所有元素都比target 大,最后r就会被减到-1. 使用index前一定注意它是否在0到length-1的范围内。

r的初始值要注意-1.

Time Complexity: O(logm + logn) = O(log(m*n)).

Space: O(1).

AC Java:

 1 public class Solution {
 2     public boolean searchMatrix(int[][] matrix, int target) {
 3         /*
 4         //Method 1
 5         if(matrix == null || matrix.length == 0 || matrix[0].length == 0){
 6             return false;
 7         }
 8         int m = matrix.length;
 9         int n = matrix[0].length;
10         int l = 0;
11         int r = m*n - 1;
12         while(l<=r){
13             int mid = l + (r-l)/2;
14             if(matrix[mid/n][mid%n] == target){
15                 return true;
16             }else if(matrix[mid/n][mid%n] > target){
17                 r = mid-1;
18             }else{
19                 l = mid+1;
20             }
21         }
22         return false;
23         */
24         //Method 2
25         if(matrix == null || matrix.length == 0 || matrix[0].length == 0){
26             return false;
27         }
28         int m = matrix.length;
29         int n = matrix[0].length;
30         int l = 0; 
31         int r = m-1;    //error
32         while(l<=r){
33             int mid = l+(r-l)/2;
34             if(matrix[mid][0] == target){
35                 return true;
36             }else if(matrix[mid][0] > target){
37                 r = mid-1;
38             }else{
39                 l = mid+1;
40             }
41         }
42         int row = r; //跳出loop时,r肯定指向开始元素比target小的row, l肯定指向开始i比target大的row
43         //corner case, 如果第一行第一个值逗比target大,那么跳出loop时row是-1. 肯定没有符合target的值
44         if(row < 0){
45             return false;
46         }
47         l = 0;
48         r = n-1;
49         while(l<=r){
50             int mid = l+(r-l)/2;
51             if(matrix[row][mid] == target){
52                 return true;
53             }else if(matrix[row][mid] > target){
54                 r = mid-1;
55             }else{
56                 l = mid+1;
57             }
58         }
59         return false;
60     }
61 }

跟上Search a 2D Matrix II.

posted @ 2015-10-15 03:43  Dylan_Java_NYC  阅读(386)  评论(0编辑  收藏  举报