思路一: 我自己的思路其实和appraoch 3是差不多的,都是将matrix分成四个部分(虽然我和lc分的四个部分不一样,但是不要紧,都是用来缩减search space的),用的也都是recursive的方法。但是approach3定位新的matrix是用left-up和right-bottom两个点坐标来重新定位的,而我是用4个函数重新构建新matrix的。很明显,lc的方法会更好一点。这也是为什么我tle的原因。我觉得我改一下,改成两点定位的话应该也能accpted。但是我今天实在太累了,不想改了。建议复盘的时候重改代码。具体思路的话去lc看approach3思路。下面展示下approach3代码以及我自己的代码:
// 自己的代码
class Solution {
public boolean searchMatrix(int[][] matrix, int target) {
if(matrix.length == 0) return false;
if(matrix[0].length == 0) return false;
int m = matrix.length;
int n = matrix[0].length;
if(target < matrix[0][0]) return false;
if(target > matrix[m - 1][n - 1]) return false;
int left = 0;
int right = m * n - 1;
int mid = left + (right - left) / 2;
if(matrix[mid / n][mid % n] == target) return true;
else if(matrix[mid / n][mid % n] > target){
return searchMatrix(upMatrix(matrix,left,right),target) || searchMatrix(leftMatrix(matrix,left,right),target);
}else{
return searchMatrix(downMatrix(matrix,left,right),target) || searchMatrix(rightMatrix(matrix,left,right),target);
}
}
private int[][] upMatrix(int[][] matrix, int left, int right){
int n = matrix[0].length;
int mid = left + (right - left) / 2;
int row = mid / n;
int[][] res = new int[row][n];
for(int i = 0; i < row; i++){
for(int j = 0; j < n; j++){
res[i][j] = matrix[i][j];
}
}
return res;
}
private int[][] downMatrix(int[][] matrix, int left, int right){
int m = matrix.length;
int n = matrix[0].length;
int mid = left + (right - left) / 2;
int row = mid / n;
int[][] res = new int[m - 1 - row][n];
for(int i = row + 1; i < m ; i++){
for(int j = 0; j < n; j++){
res[i-1-row][j] = matrix[i][j];
}
}
return res;
}
private int[][] leftMatrix(int[][] matrix, int left, int right){
int m = matrix.length;
int n = matrix[0].length;
int mid = left + (right - left) / 2;
int col = mid % n;
int[][] res = new int[m][col];
for(int i = 0; i < m ; i++){
for(int j = 0; j < col; j++){
res[i][j] = matrix[i][j];
}
}
return res;
}
private int[][] rightMatrix(int[][] matrix, int left, int right){
int m = matrix.length;
int n = matrix[0].length;
int mid = left + (right - left) / 2;
int col = mid % n;
int[][] res = new int[m][n - 1 - col];
for(int i = 0; i < m ; i++){
for(int j = col + 1; j < n; j++){
res[i][j - col - 1] = matrix[i][j];
}
}
return res;
}
}
// lc的代码
class Solution {
private int[][] matrix;
private int target;
private boolean searchRec(int left, int up, int right, int down) {
// this submatrix has no height or no width.
if (left > right || up > down) {
return false;
// `target` is already larger than the largest element or smaller
// than the smallest element in this submatrix.
} else if (target < matrix[up][left] || target > matrix[down][right]) {
return false;
}
int mid = left + (right-left)/2;
// Locate `row` such that matrix[row-1][mid] < target < matrix[row][mid]
int row = up;
while (row <= down && matrix[row][mid] <= target) {
if (matrix[row][mid] == target) {
return true;
}
row++;
}
return searchRec(left, row, mid-1, down) || searchRec(mid+1, up, right, row-1);
}
public boolean searchMatrix(int[][] mat, int targ) {
// cache input values in object to avoid passing them unnecessarily
// to `searchRec`
matrix = mat;
target = targ;
// an empty matrix obviously does not contain `target`
if (matrix == null || matrix.length == 0) {
return false;
}
return searchRec(0, 0, matrix[0].length-1, matrix.length-1);
}
}
思路二: lc Approach 4: Search Space Reduction。这个方法很巧妙,建议直接看lc solution approach 4思路。思路其实真的挺简单的,只不过很难自己想到,下次记住就好了。我自己没有实现代码,复盘的时候建议自己实现一下。这边我直接展示lc代码:
class Solution {
public boolean searchMatrix(int[][] matrix, int target) {
// start our "pointer" in the bottom-left
int row = matrix.length-1;
int col = 0;
while (row >= 0 && col < matrix[0].length) {
if (matrix[row][col] > target) {
row--;
} else if (matrix[row][col] < target) {
col++;
} else { // found it
return true;
}
}
return false;
}
}
总结:
- approach 3 Divide and Conquer这个方法要去多了解,好像目前为止碰到两三次了。
- 这题还有binary search的解法,我看了会儿没看懂,没有耐心了,但是感觉还挺重要的,复盘的时候建议重新看一下approach 2 binary search。