题目描述
在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 32M,其他语言64M 热度指数:1539496
本题知识点: 查找、数组
解题思路
本题是二维数组中的查找,刚看到这个题时:
- 第一反应就是扒出数组规律:从左到右、从上到下递增;
- 接下来无非就是按照数组规律,设定一个查找规则,使算法效率更高;
- 这里就有了一个问题:在二维数组遍历时,按照习惯,我们一般会从数组[ 0 ][0]出发,按行列递增的顺序遍历。但是,当我们在遍历数组某个元素a [ i ] [ j ],若目标 target > a [ i ] [ j ],接下来是找a [ i+1 ] [ j ],还是a [ i ] [ j+1]?
- (当然这里直接生硬的把整个数组遍历一遍,也是能得到结果的,但是这无疑并不是题目想要的方法)
上述思路问题的关键点就在于,需要找到一种规则使得:当目标 target > a [ i ] [ j ] 或 target < a [ i ] [ j ] 时,算法只有一种遍历方向。
这里,我把数组大致表示了一下:
不难发现,任意画一条从上到下再从左往右的折线箭头(①、②、③),该箭头所穿过的数组元素都满足递增的顺序,而题目给出的数组便是由许许多多这种所谓的箭头构成。
把箭头的拐点 a [ i ] [ j ]与目标target比较:
若小于目标,则选取a [ i -1] [ j ];
若大于目标,则选取a [ i ] [ j+1 ];
这样,算法的递进过程有了,自然而然,初始时,应该选取数组最左下角的元素参与比较。
把上述过程,直白化描述成算法,就是:初始时,选择数组最左下角的元素,在与目标target比较时,若比target小,则选择该元素右边的元素;若比target大,则选择该元素上面的元素。出界时,算法结束,目标target不在该数组。
时间复杂性:O(n)
最坏情况下时间复杂性:2n
(当然,把上述过程反过来,从数组最右上角的元素开始,也是可行的)
算法描述
class Solution {
public:
bool Find(int target, vector<vector<int> > array) {
if(array.size()!= 0)
{
int row = array.size()-1;
int col = 0;//左下角元素坐标
while(row >= 0 && col < array[0].size() )//数组不越界
{
if(array[row][col] == target)
return true;//找到
else if(array[row][col] > target)
row--;//目标元素较小,往上找
else
col++;//目标元素较大,往右找
}
}
return false;
}
};
补充:
常见的查找方法
- 静态查找:
- 顺序表的查找:顺序查找、
- 有序表的查找:折半查找、斐波那契查找、插值查找
- 静态树表的查找:
- 索引顺序表的查找:
- 动态查找:
- 二叉排序树和平衡二叉树查找
- B-树和B+树查找
- 键树查找
- 哈希查找:
常见的排序方法
- 插入排序:
- 直接插入排序
- 其他插入排序:折半插入、2-路插入、表插入、
- 希尔排序(缩小增量排序)
- 快速排序:
- 冒泡排序
- 选择排序:
- 简单选择排序
- 树形选择排序
- 堆排序
- 归并排序:
- 基数排序:
- 多关键字的排序
- 链式基数排序