剑指offer系列——二维数组中的查找
Posted xym4869
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了剑指offer系列——二维数组中的查找相关的知识,希望对你有一定的参考价值。
Q:在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
C:时间限制:C/C++ 1秒,其他语言2秒空间限制:C/C++ 32M,其他语言64M
T:
来源:牛客网
感谢:@凉风起天末
分享五种解题方法,仅为拓宽思路:
(注:如果您的代码出现了段错误问题,可能是没有考虑到空数组,健壮性也是算法的一部分)
一、左下/右上元素移动法:(我使用的是这种方法,亲测有用)
十分简单巧妙,我也是看了徘徊的路人甲的题解才后知后觉;
复杂度为O(N),详见:
class Solution {
public:
bool Find(int target, vector<vector<int> > array) {
int list1 = array.size();
int list2 = array[0].size();
int line = 0;
int col = list2 - 1;
while (line < list1 && col >= 0) {
if (target < array[line][col]) {
col--;
} else if (target > array[line][col]) {
line++;
} else
return true;
}
return false;
}
};
二、二维折半查找法:
没有法一简洁明了,但是也挺好用,复杂度最坏情况为O(N * logN),此时需要查找的元素临近数组中心,不过总体性能优于方法三
二维数组分为上下左右四个边界top,bottom,left,right:
对上边界top进行折半查找,可以将二维数组位于终止点E右边的矩形Rr排除,因为终止点E小于其右边相邻的元素E+1,而E+1是右边矩形Rr的最小元素(左上元素)
同理,对下边界bottom折半,可以排除二维数组位于终止点E左边的矩形Rl排除,
对左边界left折半,可以排除二维数组位于终止点E下边的矩形Rb排除,
对右边界right折半,可以排除二维数组位于终止点E上边的矩形Rt排除,
一轮过去,边界范围缩小,对由新边界组成的矩形重复以上操作,直到范围缩小为只有一个元素
三、N行折半法:
也是很容易就能想到的方法,每一行都执行折半查找,持续N行,复杂度为O(N*logN)
四(一)、简单的十字分割法:
亲测可用,使用十字将数组等分为四个区域,中间交叉点用来判断,因为左上区域和右下区域必然冲突,所以二者必然可以排除一个,即每次至少可以排除1/4的数据,接着对剩下的三个区域进行递归操作,当然可以利用左上右下元素来判断是否落在区域内来进行优化,直到只有一个元素,递归层数为:logN,不优化的话最底层节点数为3^logN,优化后节点数会少很多,实测效率还算不错
四(二)、另一版本的十字分割法
与上一个类似,只不过这里先利用十字分割在主对角线方向上进行折半查找操作,操作结束后,终止点的左上区域与右下区域都可以排除,这样就只剩下左下、右上两个区域,然后再进行递归。感觉上效率会比上个版本好,不过这个我没有去实现验证
五、暴力法
不解释,复杂度为O(N^2)
以上是关于剑指offer系列——二维数组中的查找的主要内容,如果未能解决你的问题,请参考以下文章
剑指 Offer(C++版本)系列:剑指 Offer 04 二维数组中的查找