Description:
在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
①外层遍历,内层二分:
最直观简单的暴力搜索
class Solution {
public:
bool Find(int target, vector<vector<int> > array) {
if(array.empty())
return false;
int row = array.size();
int col = array[0].size();
for(int i=0; i<row; i++)
{
int low = 0;
int high = col-1;
while(low <= high)
{
int mid = (low + high)/2;
if(array[i][mid] == target)
return true;
else if(array[i][mid] > target)
high = mid - 1;
else
low = mid + 1;
}
}
return false;
}
};
②上述方法明显存在冗余,我们可以对外层遍历进行条件约束
class Solution {
public:
bool Find(int target, vector<vector<int> > array) {
if(array.empty())
return false;
int row = array.size();
int col = array[0].size();
for(int i=0; i<row; i++)
{
if(array[i].empty()) //列遍历操作的前提是数组非空
return false;
if(array[i][0] > target)// pruning
return false;
if(array[i][col-1] >= target) // pruning
{
int low = 0;
int high = col-1;
int mid = 0;
while(low <= high)
{
mid = (low + high) / 2;
if(array[i][mid] == target)
return true;
else if(array[i][mid] > target)
high = mid - 1;
else
low = mid + 1;
}
}
}
return false;
}
};
class Solution {
public:
bool Find(int target, vector<vector<int> > array) {
if(array.empty() || array[0].empty())
return false;
int row = array.size();
int col = array[0].size();
for(int i=0; i<row; i++)
{
if(array[i][0] > target)
return false;
if(array[i][col-1] < target)
continue;
int low = 0;
int high = col-1;
int mid = 0;
while(low <= high)
{
mid = (low + high) / 2;
if(array[i][mid] == target)
return true;
else if(array[i][mid] > target)
high = mid - 1;
else
low = mid + 1;
}
}
return false;
}
};
③递归+二维数组的二分查找:
首先定位到整个二维数组的中间位置,然后将其与 target 比较,若等于自然好可直接返回 true;若中间元素大于 target,则说明右下角的子矩阵一定是不存在target的(从上至下,从左至右递增排列),于是我们的搜索域划分缩减至左上角、左下角和右上角三个子矩阵,依次查找即可;中间元素小于 target 时同理,我们依次搜索右下角、左下角和右上角的子矩阵即可。
class Solution {
public:
bool Find(int target, vector<vector<int> > array)
{
if(array.empty() || array[0].empty())
return false;
int row = array.size();
int col = array[0].size();
return r_Find(target, array, 0, row-1, 0, col-1);
}
public:
bool r_Find(int target, vector<vector<int> > array,int x_start, int x_end, int y_start, int y_end)
{
if(x_start == x_end && y_start == y_end)
return (array[x_start][y_start] == target);
int x_mid = (x_start + x_end) / 2;
int y_mid = (y_start + y_end) / 2;
if(array[x_mid][y_mid] == target)
return true;
if(x_start > x_end || y_start > y_end)//
return false;
else if(array[x_mid][y_mid] > target)
{
//依次搜索左上角矩阵、左下角矩阵和右上角矩阵
if(r_Find(target, array, x_start, x_mid-1, y_start, y_mid-1))
return true;
if(r_Find(target, array, x_mid, x_end, y_start, y_mid-1))
return true;
if(r_Find(target, array, x_start, x_mid-1, y_mid+1, y_end))
return true;
}
else
{
//依次搜索右下角矩阵、右下角矩阵和左上角矩阵
if(r_Find(target, array, x_mid, x_end, y_mid+1, y_end))
return true;
if(r_Find(target, array, x_mid+1, x_end, y_start, y_mid))
return true;
if(r_Find(target, array, x_start, x_mid-1, y_mid+1, y_end))
return true;
}
return false;
}
};
④列、行删除进行查找:
利用左下角元素的特性(为该行最小值 && 该列最大值)来求解,小于 target 说明元素所在列均不符合要求,大于 target 则说明元素所在行过大,应该继续向上查找。
//左下角
class Solution {
public:
bool Find(int target, vector<vector<int> > array) {
if(array.empty() || array[0].empty())
return false;
int row = array.size();
int col = array[0].size();
int x = row-1;
int y = 0;
while(x >= 0 && y < col)
{
if(array[x][y] == target)
return true;
else if (array[x][y] < target)
++y;
else
--x;
}
return false;
}
};
//右上角同理
class Solution {
public:
bool Find(int target, vector<vector<int> > array) {
if(array.empty() || array[0].empty())
return false;
int row = array.size();
int col = array[0].size();
int x = 0;
int y = col - 1;
while(x < row && y >= 0)
{
if(array[x][y] == target)
return true;
else if(array[x][y] > target)
--y;
else
++x;
}
return false;
}
};