LeetCode.74 | 搜索二维矩阵

在这里插入图片描述
问题:在有序的二维数组中寻找目标值
类型:数组搜索问题

分析:有序数组查值,最快的是二分搜索。
1.可以使用二分搜索寻值,但是数组为二维数组,找中间值mid的索引不方便。解决方案就是,先算出mid,将其转换为对应的二维索引,可得matrix[mid/col][mid%col],该位置上的值即为中间值。
时间复杂度:O(log(mn)),m行数,n为列数
空间复杂度:O(1)

2.第二种二分查找则是先确认target在哪一行,再确认target在那一列。即先进行行二分,再进行列二分。
时间复杂度:O(log(m)+log(n))=O(log(mn))
空间复杂度:O(1)

3.第三种方法则是从右上角或左下角开始查值,这是因为此处的值具有两重属性:以左下角为例,该值为当前行的最小值,且为当前列的最大值。所以用该位置上的值,一次比较可消除一行或者一列的元素。速度极快。
时间复杂度:O(m+n),最坏情况为从左下角走到右上角
空间复杂度:O(1)

收获:
1.对二维数组进行二分查找时,该如何寻找到mid在数组中的索引,行索引:mid/col 列索引:mid%col
2.进行选择时,尽量挑选具有更多属性的元素进行比较,从而达到消除更多状态的目的。
3.尝试从右往左,从上至下的搜索策略,有时会有意想不到的结果。

代码:

//一次二分查找
bool searchMatrix(int **maxtrix,int matrixSize,int *matrixColSize,int target){
	if(!matrixSize||!matrixColSize)
		return false;
	int lo=0,hi=matrixSize*(*matrixColSize)-1;
	int col=(*matrixtColSize);
	
	while(lo<=hi){
		int mid=lo+((hi-lo)>>1);
		if(matrix[mid/col][mid%col]<target)
			lo=mid+1;
		else if(target<matrix[mid/col][mid%col])
			hi=mid-1;
		else 
			return true;
	}
	return false;
}

//两次二分查找
bool searchMatrix(int **matrix,int matrixSize,int *matrixColSize,int target){
	if (!matrixSize || !(*matrixColSize)) return false;  
    int left = 0, right = matrixSize - 1;
    
    while (left <= right) {
        int mid_row = left + ((right - left) >> 1);

        if (matrix[mid_row][0] > target) {
            right = mid_row - 1;  // 向上找
        }
        else if (matrix[mid_row][(*matrixColSize)-1] < target) {
            left = mid_row + 1;  // 向下 
        }
		else {
			int lo=0,hi=(*matrixColSize)-1;
			while(lo<=hi){
				int mid_col=lo+((hi-lo)>>1);
				if(matrix[mid_row][mid_col]<target)
					lo=mid_col+1;
				else if(target<matrix[mid_row][mid_col])
					hi=mid_col-1;
				else 
					return true;
			}
			return false;
		}
	}
	return false;
}

//从左下角走
bool searchMatrix(int **matrix,int matrixSize,int *matrixColSize,int target){
	if(!matrixSize || !(*matrixColSize))	return false;
	
	int row=matrixSize-1,col=0;
	while(0<=row&&col<(*matrixColSize)){
		if(matrix[row][col]<target)
			col++;
		else if(target<matrix[row][col])
			row--;
		else
			return true;
	}
	return false;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值