剑指offer 二维数组的查找

本来打算在LeetCode上刷题的,结果发现LeetCode的题有些多,还是先在牛客上刷剑指offer针对性强些。

时间限制:1秒 空间限制:32768K 热度指数:1416236

本题知识点: 查找 数组

题目描述

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

这题最不动脑子的就是暴力查找。再仔细看下题,单独一个维度的数是有序的。所以,可以想到按每一横行二分查找,算法复杂度O(nlogn)。这里我也是醉了,写个二分还越界,果然已退役就回到解放前了。这里顺便总结下二分的写法吧!

题目链接:题目链接

二分法:

class Solution {
public:
    bool Find(int target, vector<vector<int> > array) {
        int n = array.size();
        for(int i = 0; i < n; i++)
        {
            int l = 0, r = array[i].size();//上边界和下边界
            while(l < r)//这里注意
            {
                int mid =  (l + r) >> 1;
                if (array[i][mid] > target)
                {
                    r = mid;
                }
                else if (array[i][mid] < target)
                {
                    l = mid + 1;//mid+1是防止l和r相差1时陷入死循环
                }
                else
                {
                    return true;
                }
            }
        }
        return false;
    }
};

二分的几种写法:

//1.把边界[l,r]分为[l,mid]和[mid+1,r]更新时r=mid或者l=mid+1
int bsearch(int l, int r,int num)
{
    while (l < r)
    {
        int mid = l + r >> 1;
        if (mid > num) r = mid;
        else l = mid + 1;
    }
    return l;
}
//2.把边界[l,r]分为[l,mid-1],[mid,r]更新时r=mid-1或者l=mid
int bsearch(int l, int r,int num)
{
    while (l < r)
    {
        int mid = l + r >> 1;
        if (mid > num) r = mid-1;
        else l = mid;
    }
    return l;
}
//3.把边界[l,r]分为[l,mid-1],mid,[mid+1,r]更新时r=mid-1或者l=mid+1
int bsearch(int l, int r,int num)
{
    while (l <= r)//这里细节
    {
        int mid = l + r >> 1;
        if (mid > num) r = mid-1;
        else if(mid < num) l = mid+1;
        else return mid;
    }
}

写完后看看评论区,发现评论区果然多大佬。上面二分只用到了“每一行都按照从左到右递增的顺序排序”这个条件,但从上到下递增没用到。更优的思路是先把数和左下角的数比较,如果更大则往右比较,如果更小则往上走。这个算法复杂度O(n)。

class Solution {
public:
    bool Find(int target, vector<vector<int> > array) {
        int r = array.size()-1, v = 0;
        while (r >= 0 && v < array[r].size())
        {
            if (array[r][v] < target)
            {
                v++;
            }
            else if (array[r][v] > target)
            {
                r--;
            }
            else 
            {
                return true;
            }
        }
        return false;
    }
};

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值