题意:
给一个m*n的矩阵(每个行和列都升序),判断给定的整数是否在矩阵中。
分析:
我们能够从行列升序得到什么呢?能不能发现某种规律,我们能够确定一个数比matrix[ i ][ i ]还大,那么就一定比matrix[ i ][ i ]左上区域的所有数还要大。如果比matrix[ i ][ i ]小,那么比matrix[ i ][ i ]右下区域的所有数都小。所以,我们可以通过比较动态的确定区间,脑海中思考这个动态过程,怎么动态的确定呢?从边界不合适,那么从中间,之后呢?是一位一位移动吗,这样比较低效,可以采用二分确定区间。但是确定之后怎么办呢?用i,j遍历一个不规则带转弯的区间?这太复杂了。对于一个复杂问题的简化,计算机编程就是要利用宏观的动态规划(分治)的思想,既然复杂,我们就不去想怎么遍历,我们直接把这个任务交给程序,程序怎么知道这个奇形怪状的区间怎么遍历呢?不可能,我们继续划分,可以将其划分为两个或者三个矩阵。那么就好办了,矩阵嘛,我们又回到了问题的最初,所以我们只需要递归即可。
所以我们就是要通过比较大小动态的确定区间,每个区间的描述通过四条边来描述。注意关键在于递归的时候区间的变化(和划分)。
注意各种条件判断。
public class Solution {
int[][] matrix;
int target;
public boolean searchMatrix(int[][] matrix, int target) {
this.matrix = matrix;
this.target = target;
if(matrix.length == 0)
return false;
int m = matrix.length;
int n = matrix[0].length;
return helper(0, m-1, 0, n-1);
}
private boolean helper(int rlow, int rhigh, int clow, int chigh) {
if(rlow > rhigh || clow > chigh)
return false;
if(rlow == rhigh && clow == chigh)
return matrix[rlow][clow] == target;
int rmid = rlow + (rhigh - rlow)/2;
int cmid = clow + (chigh - clow)/2;
if(target < matrix[rmid][cmid]) {
return helper(rlow, rmid-1, clow, chigh) || helper(rmid, rhigh, clow, cmid-1);
}
else if(matrix[rmid][cmid] < target) {
return helper(rlow, rmid, cmid+1, chigh) || helper(rmid+1, rhigh, clow, chigh);
}
else
return true;
}
}