题目:在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样一个二维数组和一个整数,判断数组中是否含有该整数。
题目来源:《剑指Offer》——面试题4
题解
对于在二维有序数组中进行查找值的题目,可以参照一维有序数组查找值的方法——二分查找法。
举个例子,现有一个一维数组和一个二维数组:
一维数组:| 01 | 02 | 06 | 09 | 10 | 12 |
二维数组:
| 01 | 02 | 06 | 09 |
| 03 | 05 | 10 | 12 |
| 05 | 08 | 14 | 17 |
| 07 | 11 | 16 | 20 |
在进行一维的二分查找时,对于数组中的任一值,其左边的数字均比其小,其右边的数字均比其大。因此,在与一个middle值进行对比后,就可以直接排除掉一半的查询范围,如此往复,即可查找出结果。
与一维相类比,在二维数组中,对于表中任何一个数字,其正上方的所有数字均比其小,正右方的数字均比其大。因此,在与一个middle值进行对比后,可以直接排除掉一行或一列中的一部分。然后,只排除掉一行或一列中的一部分,对后序的查找依旧是极为不方便的,因为剩下的范围并不再是一个方形,不能进行如此往复的操作了。我们希望排除掉一行或一列中的一部分后,其剩下的查询范围依旧是一个方形,那么,只要这个数字是方形的一角就好了。
一个方形有四个角,首先考虑左上角,因为左上角一定是整个方形的最小值了,并不符合我们需要找middle值的基本条件,即在查找范围中,有比middle小的值,也有比middle大的值,因此左上角不在我们选取考虑的范围之内。同理,右下角也不再我们考虑的范围之内。而剩下的左下角和右上角皆满足要求,任意选取一个即可。
下面我们以左下角作为middle值进行举例查找14,此时的查找范围一直为middle的右上方区域:
- middle=7,middle比14小,即middle这一列均比14小,将middle向右方移动一位;
- middle=11,middle比14小,即middle这一列均比14小,将middle向右方移动一位;
- middle=16,middle比14大,即middle这一行均比14大,将middle向上方移动一位;
- middle=14,middle与14相等,查询结束。
代码实现
public boolean solution(int[][] matrix, int target) {
if (!checkData(matrix))
return false;
int x = matrix.length - 1, y = 0;
int xBorder = 0, yBorder = matrix[0].length - 1;
while (x >= xBorder && y <= yBorder) {
if (matrix[x][y] == target)
return true;
else if (matrix[x][y] > target)
x--;
else
y++;
}
return false;
}
———————勿因未候日光暖,擅自轻言世间寒。——《K》———————
—————————————要继续加油呀!O(∩_∩)O——————————