为了方便把在《剑指offer》中的题刷一遍,并记录自己的问题,因此特意开了此坑,希望能够坚持下去!
题目描述
在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
输入描述
array
:待查找的二维数组
target
:查找的数字
输出描述
查找 成功返回true
,查找失败返回false
解题思路
解法1:
看到这道题,我的第一反应就是:这不就是两个for
循环么?
确实,两个for
的确能够直接解决问题:
func Search(array [][]int, target int) bool {
for i := 0; i<len(array); i++ {
j := 0; j<len(array[0]); j++ {
if target == array[i][j] {
return true
}
}
}
return false
}
但是这里有一个问题,就是从array[0][0]
开始,数组中每一个元素都要和target
进行一次比较,如果是一个无序的二维数组,这种方法确实可行,但是对于一个有限定条件的二维数组,可能就不能这么简单了。
解法2:
考虑使用分治的方法。
因为数组是有规律可循的:每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。
对于数组中选取的数字,和目标数字的关系有三种情况:=,<,>
-
=
即查找成功 -
>
说明要查找的数字应该在当前位置的左边或上边 -
<
说明要查找的数字应该在当前位置的右边或下下边
进一步进行考虑,既然是一个二维数组,那么起始查找点我们是可以选择四个点的,即四个角,但是主对角线上的两个点和解法1中的起始点是没有区别的,仍然是两个for
循环的操作,因此考虑副对角线上的两个点的其中一个点作为起始点。
这样,对于这一类问题,可以使用分治方法解决:
- 查找从右上角(左下角)开始
- 若要查找的数字不在右上角(左下角),则每次可以剔除一列或一行
func Search(array [][]int, target int) bool {
row_len := len(board)
col_len := len(board[0])
// 我们从右上角的元素找起来
for r,c:=0,col_len-1; r<row_len && c>=0; {
if array[r][c] == target {
return true
}
if board[r][c] > target {
c--
continue
} else {
r++
}
}
return false
}
这样,我们就可以跳过一些不必要的数值进行查找,从而提升整体查询效率了。