剑指offer之二维数组中的查找(java)——超详细!!!

题目描述

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

public class Solution {
    public boolean Find(int target, int [][] array) {

    }
}

我们可以理解为有一个二维数组,这个数组从左到右递增,从上到下递减,需要我们在这个二维数组中找到特定值targer。

我们可以有三种解法。

暴力法

我们单纯的去遍历整个数组,去查找targer。

	//暴力法
	
	public static boolean Find(int target, int [][] array) {
		//处于严谨性,进行此类编程时最好先判断所传参数是否为空
		if(array == null || array.length==0 || array[0].length==0){
	         return false;
		}
		//遍历每一个值
		for(int i=0;i<array.length;i++){		//i表示所在行树
			for(int j=0;j<array[0].length;j++){		//j表示所在列数
				if(target==array[i][j]){	//判断是否存在值target
					return true;
				}
			}
		}
		//遍历结束,没有发现target值,返回false
		return false;
		
	}

二分查找法

除了暴力法之外,我们可以思考更简单的方式,去优化我们每一行的查找。

对于数据量小的数组,两者区别不大,但是,但数据量大时,二分查找是一个更好的选择。

(二分查找是基于顺序存储结构,如果我们碰到顺序存储的结构时,不妨考虑一下二分查找)

	//二分查找法
	
	public static boolean Find(int target, int [][] array) {
		//处于严谨性,进行此类编程时最好先判断所传参数是否为空
		int m = array.length;	//数组行数
		int n = array[0].length;	//数组列数
		if(array == null || m==0 || n==0){
	         return false;
		}
		//逐行遍历
		for(int i=0;i<m;i++){
			//判断target是否可能存在于当前行
			if(target >= array[i][0] && target <= array[i][n-1]){
				//二分查找
				int left=0;		//定义左指针
				int right = n-1;		//定义右指针
				while(left<=right){
					System.out.println(left+""+right);
					int mid = (right+left)/2;	//中间值
					if(target>array[i][mid]){
						left=mid+1;
					}
					else if(target<array[i][mid]){
						right=mid-1;
					}
					else{
						return true;
					}
				}
			}
		}
		//遍历结束,没有发现target值,返回false
		return false;
	}

从左下(右上)查找

当我们拿到这个题目时,第一想法肯定是从左上角开始查找,但我们发现我们无法控制数组下标,因为从左到右,从上到下都是递增的,所以我们开始思考是否存在一个方向使得数组横纵方向上一个递增,一个递减,从而控制数组下标进行查找。

于是,我们就有了从从左下(右上)查找的思路。

建议:做这类题时先进行思考,当有一个想法时,按照自己的思路进行下去,如果发现自己的思路存在问题,先试着改进自己的思路,多思考,多尝试,养成一种发现问题、解决问题的思维方法。对于以后的发展将会很有帮助。

/*		利用二维数组由上到下,由左到右递增的规律,
		那么选取左下角或者右上角的元素a[row][col]与target进行比较,
		当target小于元素a[row][col]时,那么target必定在元素a所在行的上边,
		即row--;
		当target大于元素a[row][col]时,那么target必定在元素a所在列的右边,
		即col++;
*/
	//从左下开始查找
	public static boolean Find(int target, int [][] array) {
	//处于严谨性,进行此类编程时最好先判断所传参数是否为空
	if (array == null || array.length == 0 || 
            (array.length == 1 && array[0].length == 0)) 
	    		return false;
	//从数组的左下角开始查找,找到左下角元素坐标
	int row = array.length-1;
	int col = 0;
	//开始遍历
	while(row >= 0 && col <= array[0].length-1){
		//当target小于元素a[row][col]时,那么target必定在元素a所在行的上边,即row--;
		if (target < array[row][col]){
			row--;
		}
				
		//当target大于元素a[row][col]时,那么target必定在元素a所在列的右边,即col++;
		else if(target > array[row][col]){
			col++;
		}
		//找到目标,返回true
		else{
			return true;
		}
	}
	//遍历结束,没有发现target值,返回false
	return false;
	}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值