思路
由于矩阵中的数是排序好的,因此具有以下数据规律:
- 以要查找的数为中心,左上小于它,右下大于他
1 解一: 数组遍历
int i = 0, j = M - 1;
while (i < N && j > 0) {
if (nums[i][j] == K) {
System.out.println("Yes");
return ;
}
else if (nums[i][j] > K) {
j --;
}
else {
i ++;
}
}
System.out.println("No");
- 其中
j --
如果在改行找不到,则下一行,核心1
2 解二:二分查找
思路: 既然可以定位到数所在的行,可以在行内进行二分查找
2.1 Bug1
- 由于按照行有顺序,按照列也有顺序,但其不是逐行逐列递增的,因此不能说可以定位在哪一行,即不能使用行后最大的元素大于要查找的元素,就说要找的元素在该行,有可能在下一行
- 在
else {
中, 如果找不到元素也会陷入本行的死循环中,而不会到下一行
int i = 0, j = M-1;
while(i < N) {
if (nums[i][j] < K) {
i++;
}
else {
// 所要查找的数在本行
int left = 0, right = j;
while (left <= right) {
int mid = (left + right) / 2;
if (nums[i][mid] == K) {
System.out.println("Yes");
return ;
}
else if (nums[i][mid] < K) {
left = mid + 1;
}
else {
right = mid - 1;
}
}
}
}
System.out.println("No");
}
2.2 Bug2
- 找不到,或者不满足条件,需要到下一行,在二分中,找不到的情况,永远在本行循环,陷入死循环
else if (nums[i][j] > K){
int i = 0, j = M-1;
while(i < N) {
if (nums[i][j] == K) {
System.out.println("Yes");
return;
}
else if (nums[i][j] > K){
// 所要查找的数在本行
int left = 0, right = j;
while (left <= right) {
int mid = (left + right) / 2;
if (nums[i][mid] == K) {
System.out.println("Yes");
return;
} else if (nums[i][mid] < K) {
left = mid + 1;
} else if (nums[i][mid] > K){
right = mid - 1;
}
}
}
else {
// 没有满足条件,下一行
i++;
}
}
2.3 正确二分查找代码
int i = 0, j = M-1;
while(i < N) {
if (nums[i][j] == K) {
System.out.println("Yes");
return;
}
else if (nums[i][j] > K){
// 所要查找的数在本行
int left = 0, right = j;
while (left <= right) {
int mid = (left + right) / 2;
if (nums[i][mid] == K) {
System.out.println("Yes");
return;
} else if (nums[i][mid] < K) {
left = mid + 1;
} else if (nums[i][mid] > K){
right = mid - 1;
}
}
}
// 没有找到,或者都不满足,直接在下一行查找
i++;
}