1. 题目描述
在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
2. 题目分析
2.1 思路一
这是二维遍历,最简单直接的方法就是两重for循环实现。如下:
class Solution {
public:
bool Find(int target, vector<vector<int> > array) {
int row = array.size();
int col = array[0].size();
for (int i = 0; i < row; i++)
{
for (int j = 0; j < col; j++)
{
if (array[i][j] == target)
{
return true;
}
}
}
return false;
}
}
此时,时间复杂度为O(n^2),虽然算法通俗易懂,但是效率太低。因此,需要思考怎样提高效率。
2.2 思路二
我们注意到题目中说,该数组从左到右、从上到下均是递增的,那么此时联想到有序数列的查找,我们应当可以找到一个更更快捷的方法。
我们考虑从左下角开始查找:
1. 如果当前array[row][col]的值小于target,那么应该到该点的右侧查找,因此col+1;
2. 如果当前array[row][col]的值大于target,那么应该到该点的上方查找,因此row-1。
同样的道理,也可以从右上角开始查找,那么为什么不从左上角或右下角开始查找呢?
假设我们从左上角开始查找,那么如果当前array[row][col]小于target,那么target可能位于当前位置的右方,也可能是下方,根本无法确定下一次查找的方向。
实现思路二的代码如下:
class Solution {
public:
bool Find(int target, vector<vector<int> > array) {
int row = 0;
int col = array[0].size() - 1;
while (row < array.size() && col >= 0)
{
if (array[row][col] == target)
{
return true;
}
else if (array[row][col] > target)
{
col--;
}
else
{
row++;
}
}
return false;
}
}
该思路的时间复杂度为O(n)(不确定是否正确??)
2.3 思路三
最后一种解法也比较直接,就是对每一行进行二分查找,则算法时间复杂度为O(mlogn),m是行数,n是列数。实现的代码如下:
class Solution {
public:
bool Find(int target, vector<vector<int> > array) {
int row = array.size();
int col = array[0].size();
for (int i = 0; i < row; i++)
{
int low = 0;
int high = col - 1;
int middle;
while (low <= high)
{
middle = (low + high) / 2;
if (array[i][middle] == target)
{
return true;
}
else if (array[i][middle] < target)
{
low = middle + 1;
}
else
{
high = middle - 1;
}
}
}
return false;