二维数组中的查找
在一个二维数组中,每一行数字都按照从左到右的顺序递增,每一列数字都按照从上到下的顺序递增,请完成一个函数,判断该数组是否含有某个数字?
例如在下面的数组查找7返回true,查找5返回false。
讲真,刚开始看到这道题我第一反应就是顺序遍历一遍查找,但是发现没有用到数字递增的条件,所以肯定不能这么做。想了一会儿没有什么思路就看书了,书上给出的方法是:
取右上角的元素,例如上图的9,如果查找的元素key比9大,去掉9所在的行,元素下移到12。如果查找的元素key比9小,则去掉9所在的列,元素左移到8。如果查找的元素key等于9直接返回true。依次这样下去直到没有元素了与key相等,返回false。
在这里,我们以查找key = 7为例,详细给出查找的过程。
有了上面的基础之后,代码就不难了,我自己的代码如下:
bool CanFind(int *a, int rows, int cols, int key)
{
int i = 0;
int j = cols - 1;//初始位置在右上角
while (i <= rows - 1 && j >= 0)
{
if (key < a[i * cols + j])
--j;//删除该列
else if (key > a[i * cols + j])
++i;//删除该行
else
return true;
}
return false;
}
写完我对照了书上的代码,发现自己有几点不足:
1. 如果是传入的参数不是合法的,比如a == nullptr的情况处理
2. 如果rows,cols是0甚至是负数的情况处理
修改过后的代码如下:
bool CanFind(int *a, int rows, int cols, int key)
{
if (a == nullptr || rows <= 0 || cols <= 0)//不合法的输入
return false;
int i = 0;
int j = cols - 1;//初始位置在右上角
while (i <= rows - 1 && j >= 0)
{
if (key < a[i * cols + j])
--j;//删除该列
else if (key > a[i * cols + j])
++i;//删除该行
else
return true;
}
return false;
}
在前面的分析中,我们选择右上角元素,其实左下角元素比如6也可以。但是其他两边左上角右下角则是不行的,比如左上角元素1,查找7的时候,由于7比1大必然在右边或者下边,但是我们却不能剔除1所在的行,也不能能剔除1所在的列这样起不到缩小范围的作用了。
PS:完整的代码以及各种情况的测试可点击剑指Offer习题解析之3_FindInPartiallySortedMatrix查看