题目描述
在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
我的解题思路:
分析发现,左上角和右下角的数分别对应着数组的最小值和最大值。二维数组中对角线的元素分别对应着行列两种情况。通过分别判断这个数是否落在该元素对应的行或列中(行列的极值分别为最左端和最下端的值)。比如落在行中,则依次遍历行中的元素。若未落在行或列中,则跳到下一个对角元素。
时间复杂度:O() 空间复杂度:O(1)
边界条件:
分析出的:输入的数不在最小值和最大值区间内;
未分析出的:输入的二维数组长度可能为空。二维数组是否为空的判断条件为三个,满足任意一个即可。
if((array==null||array.length==0)||(array.length==1&&array[0].length==0))
解题中遇到的问题:
判断问题:存在行列当中有一个满足的情况。由于我判断行和列是否满足时用的if else 语句,导致行判断完后未判断列式否满足,得出了错误的结果。解决方法:连个并列的if。
边界判断不完全。
完整代码:
public class Solution {
public boolean Find(int target, int [][] array) {
//判断是否为空
if(array == null || array.length == 0 || array[0].length == 0){
return false;
}
int arrayLength = array.length;
if(arrayLength == 0){
return false;
}
//判断超出数组最小值和最大值的情况
if(target < array[0][0] || target > array[arrayLength-1][arrayLength-1]){
return false;
}
for(int i = 0;i < arrayLength;i++){
if((target < array[i][i] || target > array[i][arrayLength-1]) && (target < array[i][i] || target > array[arrayLength-1][i])){
//代表这位置对应的行纵两列都没有目标元素
continue;
}else{
if(target >= array[i][i] && target <= array[i][arrayLength-1]){
//代表该行可能有目标元素
for(int j = i;j < arrayLength;j++){
if(array[i][j] == target){
return true;
}
}
}
//两个判断条件要并列,不能if else
if(target >= array[i][i] && target <= array[arrayLength-1][i]){
//代表该列可能有目标元素
for(int j = i;j < arrayLength;j++){
if(array[j][i] == target){
return true;
}
}
}
}
}
return false;
}
}
剑指Offer提供的解法:
这样特殊的二维矩阵有个特点:左小角和右上角的元素。以右上角为例,如果查找到元素大于右上角,那么可以排除这一行。如果小于右上角的,那么排除右上角元素所在的列。对排除后得到的二维矩阵继续选右上角进行比较,这样每次都能排除一行或一列,直到定位到目标元素。同理左下角也可以,因为这两个地方的元素都有一个特点:对应着该行和该列元素中的极大值和极小值,因此通过比较大小肯定能排除一行或一列,缩小遍历范围。好巧妙有木有!
public class Solution {
public boolean Find(int target, int [][] array) {
if(array == null || array.length == 0 || array[0].length == 0){
return false;
}
int arrayLength = array.length;
int rowIndex = 0;
int columnIndex = array.length -1;
//注意这里的循环终止条件
while(rowIndex < arrayLength && columnIndex >= 0){
int rTopCorner = array[rowIndex][columnIndex];
if(rTopCorner == target){
return true;
}
if(rTopCorner < target){
//排除右上角元素所在的行
++rowIndex;
}
if(rTopCorner > target){
//排除右上角元素所在的行
--columnIndex;
}
}
return false;
}
}
之前写了>0,导致第一列被忽略