题目描述
在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
C++的解决方法
运行效率与时间最好
思路
矩阵是有序的,从左下角来看,向上数字递减,向右数字递增,
因此从左下角开始查找,当要查找数字比左下角数字大时。右移
要查找数字比左下角数字小时,上移
class Solution {
public:
bool Find(int target, vector<vector<int>> array) {
int rowCount = array.size();
int colCount = array[0].size();
int i,j;
for(i=rowCount-1,j=0;i>=0&&j<colCount;)
{
if(target == array[i][j])
return true;
if(target < array[i][j])
{
i--;
continue;
}
if(target > array[i][j])
{
j++;
continue;
}
}
return false;
}
};
方法总结:
- 首先要晓得如何获取二维数组的列数与行数,行数的调用方法为array.size(),列数的调用方法为array[[0].size();
- 紧接着使用for循环,初始条件是从左下角开始遍历,故为i = rowCount-1,j=0;
- 判断终止状态为右上角的元素,故i>=0&&j<colCount
- 递增条件是变化的,这就是该算法的灵活之处。根据目标元素与当前数组左下角元素做比较。若目标元素小,则上移,并结束当前此次循环;若目标元素大,则右移,并结束此次循环;若就是想查找的该元素,就立即返回 true。
- 这样就对整个二维数组进行了遍历,当整个二位数组都遍历完还没返回,就只能返回false,表示数组不含有该整数!
Java方法(一)
把每一行看成有序递增的数组,利用二分查找,通过遍历每一行得到答案,时间复杂度是nlogn
public class Solution {
public boolean Find(int target,int [][] array) {
for(int i=0;i<array.length;i++){
int low=0;
int high=array[i].length-1;
while(low<=high){
int mid=(low+high)/2;
if(target>array[i][mid])
low=mid+1;
else if(target<array[i][mid])
high=mid-1;
else
return true;
}
}
return false;
}
}
方法总结:
- 最简单直接的方法,对每一行采用二分查找。
- 首先获取到二维数组的长度,行数是array.length(),列数是array[i].length();
- 得到当前行数组的首尾索引,除以2,得到中间元素的位置,比较判断当前元素与目标元素的大小,若目标元素比当前元素大,则改变最低的位置为low=mid+1;若目标元素比当前元素小,则改变最高位置high=mid-1;否则的话直接返回true.
- 若遍历完二维数组后,还未找到,则直接返回false;
Java方法(二)
利用二维数组由上到下,由左到右递增的规律, 那么选取右上角或者左下角的元素a[row][col]与target进行比较, 当target小于元素a[row][col]时,那么target必定在元素a所在行的左边, 即col–;
当target大于元素a[row][col]时,那么target必定在元素a所在列的下边, 即row++;
public class Solution {
public boolean Find(int target, int [][] array) {
int row=0;
int col=array[0].length-1;
while(row<=array.length-1&&col>=0){
if(target==array[row][col])
return true;
else if(target>array[row][col])
row++;
else
col--;
}
return false;
}
}
方法总结:
- 这种Java算法和C++的算法是一致的,不过开始的元素是从右上角开始的。
- 并且他采用的是while循环,相对于for循环,感觉更加便利!
- 由于我是一位Java开发者,故着重掌握这种方法。不过必须要承认的一点它的执行效率没有C++好!