《剑指offer》——二维数组中的查找

60 篇文章 3 订阅

更多2019年的技术文章,欢迎关注我的微信公众号:码不停蹄的小鼠松(微信号:busy_squirrel),也可扫下方二维码关注获取最新文章哦~

T:

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

Constraints:

时间限制:1秒空间限制:32768K


My Solution:

由于各行和各列都遵循一次增大的规则,给定一个数target,首先在这样一个二维数组中找到其右边界rightSide和下边界downSide,如果二维数组中有数值和target相等,那只能在这个边界的范围内,出了边界就都是比target大的数值了。

这里写图片描述

在第一行往右,找第一个大于target的数值作为该右边界;
在第一列往下,找第一个大于target的数值作为该下边界。

遍历:

整体上,采用的从右边向左,从上往下的方式进行,在一个死循环当中进行,如果找到相等值,break循环,返回true,或者越界,那就break循环,返回false。

因为第一行的右边界,是第一个比target大的数值,记为 A 0 , j A_{0,j} A0,j,也就是说其左边的一个数值 A 0 , j − 1 A_{0, j-1} A0,j1,是比target小的,这样,直接下移一格到 A 1 , j A_{1, j} A1,j,该数值是比target大的,然后依次往左走,找到第一个比target小的,如果相等,就退出,返回true,否则就再下移一格,继续进行比较。

这里写图片描述

代码如下:

	public class Solution {
	    public boolean Find(int [][] array,int target) {
	 
	       boolean flag = false;
	        //先在二维数组中找到右边界和下边界
	        int rightSide = array[0].length;
	        int downSide = array.length;
	         
	        // 判断该二维数组是否为空数组
	        if (rightSide ==0 && downSide == 1) {
	            return flag;
	        }
	         
	        // 右边界
	        for (int j = 0; j < array[0].length; j++) {
	            if (array[0][j] == target) {
	                flag = true;
	                return flag;
	            } else if (array[0][j] > target) {
	                rightSide = j;
	                break;
	            }
	        }
	         
	        // 下边界
	        for (int i = 0; i < array.length; i++) {
	            if (array[i][0] == target) {
	                flag = true;
	                return flag;
	            }else if (array[i][0] > target) {
	                downSide = i;
	                break;
	            }
	        }
	         
	        // 看是否第一个值就比target大
	        if (rightSide == 0 && downSide == 0) {
	            return flag;
	        }
	         
	        // 第一行和第一列都是不可能有相等值的,否则在前面的步骤就已经返回
	        // 自右向左,自上向下搜索
	        int i = 0;
	        int tempi = 0;
	        int j = 0;
	        while (true) {
	            for (j = rightSide-1; j > -1 && array[tempi][j] > target; j--);
	            if (j == -1) {
	                break;
	            }
	            if (array[tempi][j] == target ) {
	                flag = true;
	                break;
	            }
	            rightSide = j;  // 重新定义右界限
	             
	            for (i = tempi; i < downSide && array[i][rightSide] < target; i++);
	            if (i == downSide) {
	                break;
	            }
	            if (array[i][rightSide] == target) {
	                flag = true;
	                return flag;
	            }
	             
	            tempi = i;
	             
	        }
	         
	        return flag;
	    }
	}

别人的思路:

“觉者”发表于 2015-08-26 14:14:12:

思路:首先我们选择从左下角开始搜寻,(为什么不从左上角开始搜寻,左上角向右和向下都是递增,那么对于一个点,对于向右和向下会产生一个岔路;如果我们选择从左下脚开始搜寻的话,如果大于就向右,如果小于就向下)。

	public class Solution {
	    public boolean Find(int [][] array,int target) {
		int len = array.length-1;
	        int i = 0;
	        while((len >= 0)&& (i < array[0].length)){
	            if(array[len][i] > target){
	                len--;
	            }else if(array[len][i] < target){
	                i++;
	            }else{
	                return true;
	            }
	        }
	        return false;
	    }
	}

改进:
我的出发点与之类似,只是判断的条件多了些,其实用他的思路,也适用我的情况。
这是我的改进代码:

	public boolean Find(int [][] array, int target) {
		boolean flag = false;
		
		int rowLen = array.length;
		int colLen = array[0].length;
		int j = colLen -1;
		int i = 0;
		
		while (i < rowLen && j > -1) {
			if (array[i][j] > target) {
				j --;
			} else if (array[i][j] < target) {
				i ++;
			} else {
				flag = true;
				return flag;
			}
		}
		
		return flag;
	}

在这个代码里面,就不需要考虑该二维数组是否为空的情况,但是在我的第一版代码中,由于需要界定边界,需要考虑二维数组是否为空的情况。
判断是否为空,这一情况很多人都会忽略掉,这是大家的惯性思维使然,思考问题的不全面导致。

更多2019年的技术文章,欢迎关注我的微信公众号:码不停蹄的小鼠松(微信号:busy_squirrel),也可扫下方二维码关注获取最新文章哦~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值