LeetCode 240 - Search a 2D Matrix II


https://leetcode.com/problems/search-a-2d-matrix-ii/
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 in ascending from left to right.
  • Integers in each column are sorted in ascending from top to bottom.
For example,
Consider the following 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]
]
Given target = 5, return true.
  • Time Complexity: O(m + n)
Given target = 20, return false.
// 从左下角开始,尝试不断向右边走 // 右边走不动了,就向下面走,直到出边界 public boolean searchMatrix(int[][] matrix, int target) { int row = matrix.length; if (row == 0) { return false; } int col = matrix[0].length; // 从左下角开始搜索 int x = row - 1; int y = 0; // 每次考虑向上走 while (x >= 0) { // 向上走之前,尽量向右边走 while (y < col && matrix[x][y] < target) { y++; } if (y < col && matrix[x][y] == target) { return true; } x--; } return false; }

public boolean searchMatrix(int[][] matrix, int target) { int row = matrix.length; if (row == 0) { return false; } int col = matrix[0].length; // 从左下角开始搜索 int x = row - 1; int y = 0; // 每次考虑向右边走 while (y < col) { // 向右边走之前,尽量向上走 while (x >= 0 && matrix[x][y] > target) { x--; } // 走不动了,再向右边走 if (x >= 0 && matrix[x][y] == target) { return true; } y++; } return false; }

public boolean searchMatrix(int[][] matrix, int target) { int row = matrix.length; if (row == 0) { return false; } int col = matrix[0].length; // 从右上角开始搜索 int x = 0; int y = col - 1; // 每次考虑向下走 while (x < row) { // 向下走之前,尽量向左边走 while (y >= 0 && matrix[x][y] > target) { y--; } if (y >= 0 && matrix[x][y] == target) { return true; } x++; } return false; }

https://leetcode.com/problems/search-a-2d-matrix-ii/discuss/66140/My-concise-O(m%2Bn)-Java-solution
public boolean searchMatrix(int[][] matrix, int target) { if(matrix == null || matrix.length < 1 || matrix[0].length <1) { return false; } int col = matrix[0].length-1; int row = 0; while(col >= 0 && row <= matrix.length-1) { if(target == matrix[row][col]) { return true; } else if(target < matrix[row][col]) { col--; } else if(target > matrix[row][col]) { row++; } } return false; }
 it's also OK to search from the bottom-left point. Just check the code below.
public static boolean searchMatrix(int[][] matrix, int target) { if (matrix == null || matrix.length < 1 || matrix[0].length < 1) return false; int col = 0; int row = matrix.length - 1; while (col <= matrix[0].length - 1 && row >= 0) { if (target == matrix[row][col]) return true; else if (target < matrix[row][col]) row--; else if (target > matrix[row][col]) col++; } return false; }
http://bookshadow.com/weblog/2015/07/23/leetcode-search-2d-matrix-ii/

O(m * logn)解法:循环枚举行,二分查找列

def searchMatrix(self, matrix, target): y = len(matrix[0]) - 1 def binSearch(nums, low, high): while low <= high: mid = (low + high) / 2 if nums[mid] > target: high = mid - 1 else: low = mid + 1 return high for x in range(len(matrix)): y = binSearch(matrix[x], 0, y) if matrix[x][y] == target: return True return False

O(n ^ 1.58)解法:

参考:https://leetcode.com/discuss/47528/c-with-o-m-n-complexity
分治法,以矩形中点为基准,将矩阵拆分成左上,左下,右上,右下四个区域
若中点值 < 目标值,则舍弃左上区域,从其余三个区域再行查找
若中点值 > 目标值,则舍弃右下区域,从其余三个区域再行查找
时间复杂度递推式:T(n) = 3T(n/2) + c
相关博文:http://articles.leetcode.com/2010/10/searching-2d-sorted-matrix-part-ii.html
public boolean searchMatrix(int[][] matrix, int target) { int n=matrix.length, m=matrix[0].length; return helper(matrix,0,n-1,0,m-1,target); } boolean helper(int[][] matrix, int rowStart, int rowEnd, int colStart, int colEnd, int target ){ if(rowStart>rowEnd||colStart>colEnd){ return false; } int rm=(rowStart+rowEnd)/2, cm=(colStart+colEnd)/2; if(matrix[rm][cm]== target){ return true; } else if(matrix[rm][cm] >target){ return helper(matrix, rowStart, rm-1,colStart, cm-1,target)|| helper(matrix, rm, rowEnd, colStart,cm-1,target) || helper(matrix, rowStart, rm-1,cm, colEnd,target); } else{ return helper(matrix, rm+1, rowEnd, cm+1,colEnd,target)|| helper(matrix, rm+1, rowEnd, colStart,cm,target) || helper(matrix, rowStart, rm,cm+1, colEnd,target); }

http://www.jyuan92.com/blog/leetcode-search-a-2d-matrix-ii/
Divide-Conquer,Based on the mid of the matrix, divide the whole matrix into four parts: left-top, left-bottom, right-top, right-bottom
  • If the mid is smaller than target, abandon the left-top area, recursion from the other three areas.
  • If the mid is larger than target, abandon the right-bottom area, recursion from the other three ares.
  • Time Complexity formula:T(n) = 3T(n/2) + c
public boolean searchMatrixImprove(int[][] matrix, int target) {
    if (null == matrix || matrix.length == 0) {
        return false;
    }
    return helper(matrix, 0, matrix.length - 1, 0, matrix[0].length - 1, target);
}
private boolean helper(int[][] matrix, int rowStart, int rowEnd, int colStart, int colEnd, int target) {
    if (rowStart > rowEnd || colStart > colEnd) {
        return false;
    }
    int rowMid = rowStart + (rowEnd - rowStart) / 2;
    int colMid = colStart + (colEnd - colStart) / 2;
    if (matrix[rowMid][colMid] == target) {
        return true;
    } else if (matrix[rowMid][colMid] > target) {
        return helper(matrix, rowStart, rowMid - 1, colStart, colMid - 1, target) ||
                helper(matrix, rowMid, rowEnd, colStart, colMid - 1, target) ||
                helper(matrix, rowStart, rowMid - 1, colMid, colEnd, target);
    } else {
        return helper(matrix, rowMid + 1, rowEnd, colMid + 1, colEnd, target) ||
                helper(matrix, rowMid + 1, rowEnd, colStart, colMid, target) ||
                helper(matrix, rowStart, rowMid, colMid + 1, colEnd, target);
    }
}
https://discuss.leetcode.com/topic/33240/java-an-easy-to-understand-divide-and-conquer-method
The coding seems to be much more complex than those smart methods such as this one, but the idea behind is actually quite straightforward. Unfortunately, it is not as fast as the smart ones.
First, we divide the matrix into four quarters as shown below:
  zone 1      zone 2
*  *  *  * | *  *  *  *
*  *  *  * | *  *  *  *
*  *  *  * | *  *  *  *
*  *  *  * | *  *  *  *
-----------------------
*  *  *  * | *  *  *  *
*  *  *  * | *  *  *  *
*  *  *  * | *  *  *  *
*  *  *  * | *  *  *  *
  zone 3      zone 4
We then compare the element in the center of the matrix with the target. There are three possibilities:
  • center < target. In this case, we discard zone 1 because all elements in zone 1 are less than target.
  • center > target. In this case, we discard zone 4.
  • center == target. return true.
For time complexity, if the matrix is a square matrix of size nxn, then for the worst case,
T(nxn) = 3T(n/2 x n/2)
which makes
T(nxn) = O(n^log3)
 public boolean searchMatrix(int[][] matrix, int target) {
    int m = matrix.length;
    if(m<1) return false;
    int n = matrix[0].length;
    
    return searchMatrix(matrix, new int[]{0,0}, new int[]{m-1, n-1}, target);
}

private boolean searchMatrix(int[][] matrix, int[] upperLeft, int[] lowerRight, int target) {
 if(upperLeft[0]>lowerRight[0] || upperLeft[1]>lowerRight[1]
   || lowerRight[0]>=matrix.length || lowerRight[1]>=matrix[0].length) 
  return false;
 if(lowerRight[0]-upperLeft[0]==0 && lowerRight[1]-upperLeft[1]==0)
  return matrix[upperLeft[0]][upperLeft[1]] == target;
 int rowMid = (upperLeft[0] + lowerRight[0]) >> 1;
 int colMid = (upperLeft[1] + lowerRight[1]) >> 1;
 int diff = matrix[rowMid][colMid] - target;
 if(diff > 0) {
  return searchMatrix(matrix, upperLeft, new int[]{rowMid, colMid}, target)
    || searchMatrix(matrix, new int[]{upperLeft[0],colMid+1}, new int[]{rowMid, lowerRight[1]}, target)
    || searchMatrix(matrix, new int[]{rowMid+1,upperLeft[1]}, new int[]{lowerRight[0], colMid}, target);
 }
 else if(diff < 0) {
   return searchMatrix(matrix, new int[]{upperLeft[0], colMid+1}, new int[]{rowMid, lowerRight[1]}, target)
    || searchMatrix(matrix, new int[]{rowMid+1, upperLeft[1]}, new int[]{lowerRight[0], colMid}, target)
    || searchMatrix(matrix, new int[]{rowMid+1, colMid+1}, lowerRight, target);
 }
 else return true;
}
Searching a 2D Sorted Matrix II | LeetCode
From book - cracking code
Coordinate findElement(int[][] matrix, Coordinate or1g1n, Coordinate dest, int x){
 if (!origin.inbounds (matrix) || ! dest.inbounds(matrix)) {
 return null;
}
if (matrix[origin.row][origin.column]
return origin;
} else if (!origin.isBefore(dest)) {
return null;
 }

 /* Set start to start of diagonal and end to the end of the diagonal. Since the
 * grid may not be square, the end of the diagonal may not equal dest. */
 Coordinate start= (Coordinate) origin.clone();
 int diagDist = Math.min(dest.row - origin.row, dest.column - origin.column);
 Coordinate end= new Coordinate(start.row + diagDist, start.column + diagDist);
 Coordinate p = new Coordinate(0, 0);

 /* Do binary search on the diagonal, looking for the first element> x */
 while (start.isBefore(end)) {
 p.setToAverage(start, end);
 if (x > matrix[p.row][p.column]) {
 start.row = p.row + 1;
 start.column = p.column + 1;
 } else {
 end.row = p.row - 1;
 end.column = p.column - 1;
 }
 }

 /* Split the grid into quadrants. Search the bottom left and the top right. */
 return partitionAndSearch(matrix, origin, dest, start, x);
 }

 Coordinate partitionAndSearch(int[][] matrix, Coordinate origin, Coordinate dest,
 Coordinate pivot, int x) {
 Coordinate lowerLeftOrigin = new Coordinate(pivot.row, origin.column);
 Coordinate lowerLeftDest = new Coordinate(dest.row, pivot.column - 1);
 Coordinate upperRightOrigin = new Coordinate(origin.row, pivot.column);
 coordinate upperRightDest = new Coordinate(pivot.row - 1, dest.column);

 Coordinate lowerLeft = findElement(matrix, lowerLeftOrigin, lowerLeftDest, x);
 if (lowerleft == null) {
 return findElement(matrix, upperRightOrigin, upperRightDest, x);
 }
 return lowerleft;
 }

 Coordinate findElement(int[][] matrix, int x) {
 Coordinate origin = new Coordinate(0, 0);
 coordinate dest = new Coordinate(matrix.length - 1, matrix[0].length - 1);
 return findElement(matrix, origin, dest, x);
 }

 public class Coordinate implements Cloneable {
 public int row, column;
 public Coordinate(int r, int c) {
 row = r;
 column = c;
 }

 public boolean inbounds(int[][] matrix) {
 return row >= 0 && column >= 0 &&
 row< matrix.length && column< matrix[0].length;
 }

 public boolean isBefore(Coordinate p) {
 return row<= p.row && column<= p.column;
 }

 public Object clone() {
 return new Coordinate(row, column);
 }

 public void setToAverage(Coordinate min, Coordinate max) {
 row = (min.row + max.row) / 2;
 column = (min.column + max.column)/ 2;
 }
 }

Labels

LeetCode (1432) GeeksforGeeks (1122) LeetCode - Review (1067) Review (882) Algorithm (668) to-do (609) Classic Algorithm (270) Google Interview (237) Classic Interview (222) Dynamic Programming (220) DP (186) Bit Algorithms (145) POJ (141) Math (137) Tree (132) LeetCode - Phone (129) EPI (122) Cracking Coding Interview (119) DFS (115) Difficult Algorithm (115) Lintcode (115) Different Solutions (110) Smart Algorithm (104) Binary Search (96) BFS (91) HackerRank (90) Binary Tree (86) Hard (79) Two Pointers (78) Stack (76) Company-Facebook (75) BST (72) Graph Algorithm (72) Time Complexity (69) Greedy Algorithm (68) Interval (63) Company - Google (62) Geometry Algorithm (61) Interview Corner (61) LeetCode - Extended (61) Union-Find (60) Trie (58) Advanced Data Structure (56) List (56) Priority Queue (53) Codility (52) ComProGuide (50) LeetCode Hard (50) Matrix (50) Bisection (48) Segment Tree (48) Sliding Window (48) USACO (46) Space Optimization (45) Company-Airbnb (41) Greedy (41) Mathematical Algorithm (41) Tree - Post-Order (41) ACM-ICPC (40) Algorithm Interview (40) Data Structure Design (40) Graph (40) Backtracking (39) Data Structure (39) Jobdu (39) Random (39) Codeforces (38) Knapsack (38) LeetCode - DP (38) Recursive Algorithm (38) String Algorithm (38) TopCoder (38) Sort (37) Introduction to Algorithms (36) Pre-Sort (36) Beauty of Programming (35) Must Known (34) Binary Search Tree (33) Follow Up (33) prismoskills (33) Palindrome (32) Permutation (31) Array (30) Google Code Jam (30) HDU (30) Array O(N) (29) Logic Thinking (29) Monotonic Stack (29) Puzzles (29) Code - Detail (27) Company-Zenefits (27) Microsoft 100 - July (27) Queue (27) Binary Indexed Trees (26) TreeMap (26) to-do-must (26) 1point3acres (25) GeeksQuiz (25) Merge Sort (25) Reverse Thinking (25) hihocoder (25) Company - LinkedIn (24) Hash (24) High Frequency (24) Summary (24) Divide and Conquer (23) Proof (23) Game Theory (22) Topological Sort (22) Lintcode - Review (21) Tree - Modification (21) Algorithm Game (20) CareerCup (20) Company - Twitter (20) DFS + Review (20) DP - Relation (20) Brain Teaser (19) DP - Tree (19) Left and Right Array (19) O(N) (19) Sweep Line (19) UVA (19) DP - Bit Masking (18) LeetCode - Thinking (18) KMP (17) LeetCode - TODO (17) Probabilities (17) Simulation (17) String Search (17) Codercareer (16) Company-Uber (16) Iterator (16) Number (16) O(1) Space (16) Shortest Path (16) itint5 (16) DFS+Cache (15) Dijkstra (15) Euclidean GCD (15) Heap (15) LeetCode - Hard (15) Majority (15) Number Theory (15) Rolling Hash (15) Tree Traversal (15) Brute Force (14) Bucket Sort (14) DP - Knapsack (14) DP - Probability (14) Difficult (14) Fast Power Algorithm (14) Pattern (14) Prefix Sum (14) TreeSet (14) Algorithm Videos (13) Amazon Interview (13) Basic Algorithm (13) Codechef (13) Combination (13) Computational Geometry (13) DP - Digit (13) LCA (13) LeetCode - DFS (13) Linked List (13) Long Increasing Sequence(LIS) (13) Math-Divisible (13) Reservoir Sampling (13) mitbbs (13) Algorithm - How To (12) Company - Microsoft (12) DP - Interval (12) DP - Multiple Relation (12) DP - Relation Optimization (12) LeetCode - Classic (12) Level Order Traversal (12) Prime (12) Pruning (12) Reconstruct Tree (12) Thinking (12) X Sum (12) AOJ (11) Bit Mask (11) Company-Snapchat (11) DP - Space Optimization (11) Dequeue (11) Graph DFS (11) MinMax (11) Miscs (11) Princeton (11) Quick Sort (11) Stack - Tree (11) 尺取法 (11) 挑战程序设计竞赛 (11) Coin Change (10) DFS+Backtracking (10) Facebook Hacker Cup (10) Fast Slow Pointers (10) HackerRank Easy (10) Interval Tree (10) Limited Range (10) Matrix - Traverse (10) Monotone Queue (10) SPOJ (10) Starting Point (10) States (10) Stock (10) Theory (10) Tutorialhorizon (10) Kadane - Extended (9) Mathblog (9) Max-Min Flow (9) Maze (9) Median (9) O(32N) (9) Quick Select (9) Stack Overflow (9) System Design (9) Tree - Conversion (9) Use XOR (9) Book Notes (8) Company-Amazon (8) DFS+BFS (8) DP - States (8) Expression (8) Longest Common Subsequence(LCS) (8) One Pass (8) Quadtrees (8) Traversal Once (8) Trie - Suffix (8) 穷竭搜索 (8) Algorithm Problem List (7) All Sub (7) Catalan Number (7) Cycle (7) DP - Cases (7) Facebook Interview (7) Fibonacci Numbers (7) Flood fill (7) Game Nim (7) Graph BFS (7) HackerRank Difficult (7) Hackerearth (7) Inversion (7) Kadane’s Algorithm (7) Manacher (7) Morris Traversal (7) Multiple Data Structures (7) Normalized Key (7) O(XN) (7) Radix Sort (7) Recursion (7) Sampling (7) Suffix Array (7) Tech-Queries (7) Tree - Serialization (7) Tree DP (7) Trie - Bit (7) 蓝桥杯 (7) Algorithm - Brain Teaser (6) BFS - Priority Queue (6) BFS - Unusual (6) Classic Data Structure Impl (6) DP - 2D (6) DP - Monotone Queue (6) DP - Unusual (6) DP-Space Optimization (6) Dutch Flag (6) How To (6) Interviewstreet (6) Knapsack - MultiplePack (6) Local MinMax (6) MST (6) Minimum Spanning Tree (6) Number - Reach (6) Parentheses (6) Pre-Sum (6) Probability (6) Programming Pearls (6) Rabin-Karp (6) Reverse (6) Scan from right (6) Schedule (6) Stream (6) Subset Sum (6) TSP (6) Xpost (6) n00tc0d3r (6) reddit (6) AI (5) Abbreviation (5) Anagram (5) Art Of Programming-July (5) Assumption (5) Bellman Ford (5) Big Data (5) Code - Solid (5) Code Kata (5) Codility-lessons (5) Coding (5) Company - WMware (5) Convex Hull (5) Crazyforcode (5) DFS - Multiple (5) DFS+DP (5) DP - Multi-Dimension (5) DP-Multiple Relation (5) Eulerian Cycle (5) Graph - Unusual (5) Graph Cycle (5) Hash Strategy (5) Immutability (5) Java (5) LogN (5) Manhattan Distance (5) Matrix Chain Multiplication (5) N Queens (5) Pre-Sort: Index (5) Quick Partition (5) Quora (5) Randomized Algorithms (5) Resources (5) Robot (5) SPFA(Shortest Path Faster Algorithm) (5) Shuffle (5) Sieve of Eratosthenes (5) Strongly Connected Components (5) Subarray Sum (5) Sudoku (5) Suffix Tree (5) Swap (5) Threaded (5) Tree - Creation (5) Warshall Floyd (5) Word Search (5) jiuzhang (5)

Popular Posts