剑指offer-在二维数组中查找

在一个 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
}
posted @ 2021-12-21 17:56  西*风  阅读(33)  评论(0编辑  收藏  举报