【二分查找】二维数组中的查找

链接:https://www.nowcoder.com/questionTerminal/abc3fe2ce8e146608e868a70efebf62e
来源:牛客网
 

两种思路

一种是:

把每一行看成有序递增的数组,

利用二分查找,

通过遍历每一行得到答案,

时间复杂度是nlogn

我之前写二分法都是想着用递归来实现,不得不重新定义一个函数,其实不用,只需要用一个while循环就行了。

public class Solution {

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

         

        for(int i=0;i<array.length;i++){

            int low=0;

            int high=array[i].length-1;

            while(low<=high){

                int mid=(low+high)/2;

                if(target>array[i][mid])

                    low=mid+1;

                else if(target<array[i][mid])

                    high=mid-1;

                else

                    return true;

            }

        }

        return false;



    }

}

 

另外一种思路是:

利用二维数组由上到下,由左到右递增的规律,

本来是以为:比你大有两种可能,①在你下面 ②在你右边。所以这就造成了编程的难度。

但是!!!如果规定先从左下角开始比较,那么这种可能性就只能有一个了

那么选取左下角的元素a[row][col]与target进行比较,

当target小于元素a[row][col]时,那么target必定在元素a所在行的左边,

即col--;

当target大于元素a[row][col]时,那么target必定在元素a所在列的下边,

即row++;

bool Find(int target, vector<vector<int> > array) {

         int row=array.size()-1;
        int col=array[0].size()-1;
        int i=row;
        int j=0;
        while(i>=0 && j<=col){
            if(target==array[i][j])
                return true;
            else if(target>array[i][j])
                j++;
            else
                i--;
        }
        return false;
    }

 

 

另外一道二分查找的题:

大致思路:

先对每一行的第一个元素来进行二分查找,找到target所在的行,然后对该行进行二分查找。

经过模拟,我发现在第一种(对第一列的)二分查找中,二分查找的if语句if(low<=high)需要修改,因为存在一种情况是:

1 2 3 4

5 6 7 8

此时low=1,high=2,要查找的数是3,但matrix[mid][0]总是等于1,你不能让low = mid+1,因为那样low变成2会错过。所以等到low==high-1就应该停下循环了。通过模拟,发现停下来之后,target有可能在low,有可能在high==low+1行上。进行两次在行上的二分查找。这个二分查找就是常规的了,不过要注意if(low<=high),不要写落了=,因为比如对于[1,3],target是3,如果写掉=则刚刚找到low==high==3所在的位置,就退出循环了。

总之,这种情况举个例子多模拟几下,注意常规的二分查找if(low<=high)

AC代码:

class Solution {
public:
    bool searchMatrix(vector<vector<int> > &matrix, int target) {
        if(matrix.size()==0)
            return false;
        if(matrix.size()==1 && matrix[0].size()==1 && target == matrix[0][0])
            return true;
        
        //对每行第一个元素二分查找
        int row = matrix.size();
        int col = matrix[0].size();
        int low=0;
        int high=row-1;
        while(low<high && low+1!=high)
        {
            int mid = (low+high)/2;
            if(matrix[mid][0]==target)
                return true;
            if(matrix[mid][0]<target)
                low=mid;  //不能low=mid+1,因为这不代表low排上没有target
            if(matrix[mid][0]>target)
                high = mid-1;  //可以high=mid-1,因为这代表high排上没有target
        }
        //现在肯定满足在low或者high排上
        //先找Low排
        //在low排上进行二分查找
        int left = 0;
        int right = col-1;
        while(left<=right)
        {
            int mid = (left+right)/2;
            if(matrix[low][mid]==target)
                return true;
            if(matrix[low][mid]<target)
                left=mid+1;
            if(matrix[low][mid]>target)
                right = mid-1;
        }
        //在high排上进行二分查找
        left =0;
        right = col-1;
        while(left<=right)
        {
            int mid = (left+right)/2;
            if(matrix[high][mid]==target)
                return true;
            if(matrix[high][mid]<target)
                left=mid+1;
            if(matrix[high][mid]>target)
                right = mid-1;
        }
        
        return false;
    }
};

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值