在一个 n * m 的二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个高效的函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
示例:
现有矩阵 matrix 如下:
[
[1, 4, 7, 11, 15],
[2, 5, 8, 12, 19],
[3, 6, 9, 16, 22],
[10, 13, 14, 17, 24],
[18, 21, 23, 26, 30]
]
给定 target = 5,返回 true。
给定 target = 20,返回 false。
限制:
0 <= n <= 1000
0 <= m <= 1000
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/er-wei-shu-zu-zhong-de-cha-zhao-lcof
解析:
方案1: 二叉搜索法!
由题目可以知道,对于右上角的元素,其左边列的元素必定比它小,其下面行的元素必定比它大,所以从右上角开始搜索,遇到比target大的元素,则往左边列搜索,遇到比target小的元素,则往下一行搜索,如果搜索到左下角,还没有搜索到,则是不存在target元素
func findNumberIn2DArray(matrix [][]int, target int) bool {
if matrix==nil || len(matrix)==0{
return false
}
indexI:=0
indexJ:=len(matrix[indexI])-1
if indexJ==-1{
return false
}
for {
if indexI>=len(matrix) || indexJ<0{
return false
}
//fmt.Println("当前查找值:",matrix[indexI][indexJ])
if indexI==len(matrix)-1 && indexJ==0 && matrix[indexI][indexJ]!=target{
return false
}
if matrix[indexI][indexJ]==target{
return true
}else if matrix[indexI][indexJ]>target{
indexJ-=1
}else if matrix[indexI][indexJ]<target{
indexI+=1
}
}
}
方案二:两次二分查找,先二分找到是哪些行可能存在target,再遍历这么行,对每行进行二分,查找可能是这一行的那一列
func findNumberIn2DArray(matrix [][]int, target int) bool {
if len(matrix)==0 || matrix==nil{
return false
}
var nums []int
for i := 0; i < len(matrix); i++ {
if len(matrix[i])!=0{ // 数组里面有东西才加入
nums = append(nums, matrix[i][0])
}
}
indexI := sort.Search(len(nums), func(i int) bool {
return nums[i] >= target
})
//fmt.Println("indexI: ",indexI)
//fmt.Println("nums:",nums)
if indexI==len(nums){ // 没找到>=target的第一个数字
indexI-=1
}
// 找到了>=target的第一个数字
for i:=indexI;i>=0;i--{
indexJ:=sort.Search(len(matrix[i]), func(j int) bool {
return matrix[i][j]>=target
})
for j:=indexJ;j<len(matrix[i]);j++{
if matrix[i][j]==target{
return true
}
}
}
return false
}