【剑指 offer】二 维 数 组 中 的 查 找

请添加图片描述

✨个人主页:bit me
✨当前专栏:算法训练营

二 维 数 组 中 的 查 找

核心考点:数组相关,特性观察,时间复杂度把握

描述:

在一个二维数组array中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。

[[1,2,8,9],[2,4,9,12],[4,7,10,13],[6,8,11,15]]

给定 target = 7,返回 true。
给定 target = 3,返回 false。

数据范围:矩阵的长宽满足 0 <= n,m <= 500,矩阵中的值满足 0 <= val <= 10^9

进阶:空间复杂度 O(1) ,时间复杂度 O(n+m)

示例1:

输入:7,[[1,2,8,9],[2,4,9,12],[4,7,10,13],[6,8,11,15]]
 
返回值:true
 
说明:存在7,返回true

示例2:

输入:1,[[2]]

 
返回值:false
 

示例3:

输入:3,[[1,2,8,9],[2,4,9,12],[4,7,10,13],[6,8,11,15]]

 
返回值:false
 
说明:不存在3,返回false

思路:

这一题首先查找元素,我们首先想到的肯定是遍历数组,一个一个元素查找,这时候咱们的思路就被限制了,一次查找一个,效率极其低下,因此我们还得找一个更好的办法

  • 查找的过程,本质是一个排除的过程
     
    根据题目的特性,从左到右依次递增,从上到下依次递增,于是我们定两个点,一个是右上角的点,一个是左下角的点。如图:
    在这里插入图片描述
    所以我们在这里就直接可以用我们要查找的元素和右上角的元素进行比较,当要查找的元素比右上角元素大的时候,我们就可以直接把最上面那一行都舍去,因为从左到右依次递增最右边的数值就是最大的,要查找的元素比最大的元素还大那就肯定不在这一行;当要查找的元素比右上角元素小的时候,就可以直接省去最右边的一列,道理是一样的,然后继续这样比较下去。
     
  • 注意:临界条件

代码实现:

  1. 先考虑特殊情况,数组为空的时候
if(array == null){
	return false;
}
  1. 定义下标,为了取到右上角元素
int i = 0;
int j = array[0].length - 1;

注意 i 是行,j 是列,其中 array[0].length - 1 是代表第一行的长度减去 1 ,就是第一行最后一个元素的下标,因为下标都是从 0 开始的。

  1. 用循环来判断并且排除
while( i < array.length && j >= 0){
	if(target < array[i][j]){//array[i][j]一定是当前行最大的,当前列最小的
		//target < array[i][j] 排除当前列
		j--;
	}
	else if(target > array[i][j]){
		//target > array[i][j] 排除当前行
		i++;
	}
	else{
		//找到
		return true;
	}
}
return false;
  • while 循环中的条件就是行 i 和列 j 都需要有合法性,i 是行,必须要有元素才可以,无论几行,j 是列,可以是一列及其以上,下标从 0 开始,所以大于等于 0 。
  • 当查找的值小于右上角的值的时候,就可以把最右边的一列省去,因为从上往下递增,右上角最小
  • 当查找的值大于右上角的值的时候,就可以把最上面的一行省去,因为从左往右递增,右上角最大

附上总的代码

public class Solution {
	public boolean Find(int target, int [][] array) {
		if(array == null){
			return false;
		}
		int i = 0;
		int j = array[0].length - 1;
		while( i < array.length && j >= 0){
			if(target < array[i][j]){//array[i][j]一定是当前行最大的,当前列最小的
				//target < array[i][j] 排除当前列
				j--;
			}
			else if(target > array[i][j]){
				//target > array[i][j] 排除当前行
				i++;
			}
			else{
				//找到
				return true;
			}
		}
		return false;
	}
}
评论 23
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Redamancy丶早晚

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值