【题目】 给定一个有N*M的整形矩阵matrix和一个整数K,matrix的每一行和每一列都是排好序的。实现一个函数判断K是否在matrix中。例如:
0 1 2 5
2 3 4 7
4 4 4 8
5 7 7 9
如果K为7,则返回true;如果K为6,返回false。
要求: 时间复杂度为O(N+M),额外空间复杂度为O(1)。
【解答】
可以将问题抽象成下面的模型:
数字越大,颜色越深,给了一个灰色方块,让你找到这个颜色的方块位于哪里
查找的这个方块应该从右上或者左下开始走,逐一对比。在任意时刻可以简化出这样一个模型:
即:同一时刻,往下走更黑,往左走更白。根据自己与当前位置方格颜色比较,决定走向更白还是更黑的地方
1)如果颜色相同则找到了。
2)如果自己的颜色比此位置方块浅,那么向左走,因为向下只会更黑
3)如果自己的颜色比此位置方块深,那么应该向下走,走向更黑的地方去比较。
为什么不能从左上角或者右下角开始走?
因为那样用不了排除法。只能一个一个比较(O(n))。假如从左上角开始对比颜色,往右和往下都是变得更黑,所以不知道应该往哪里走。同样右下角开始,往上和往左都是变浅。还是不知道往哪里走。而我们要构建的就是在对角线上这种“非黑即白”的感觉,才能做出确定的选择。
/**
*从排好序的矩阵中找数,每一行和每一列都排好序
* @author liq
*
*/
public class Code09_FindNumInSortedMatrix {
public static boolean isContains(int[][] matrix, int num) {
//开始位置:右上角
int row = 0;
int col = matrix[0].length - 1;
while (row <= matrix.length-1 && col >= 0) {//不超过边界
if (num == matrix[row][col]) { //直接命中
return true;
}else if (num < matrix[row][col]) { //自己颜色比当前浅,向左走,因为向下更黑
col --;
}else { //自己颜色比当前颜色深,向下走向更黑的地方
row ++;
}
}
return false;
}