刷题总结-二分查找

704.二分查找

写二分查找时需要格外注意搜索区间的定义,我在第一次写时因为这一点导致代码陷入了死循环。

class solution1 {
    int binarySearch(vector<int>& nums, int target)
    {
        int left = 0;
        int right = nums.size() - 1;
        int mid;
        while (left <= right)
        {
            mid = (left + right) / 2;


            if (nums[mid] == target)
            {
                return mid;
            }
            else if (nums[mid] > target)//target<nums[mid]时,target下标在[begin,mid-1]
            {
                right = mid - 1;/*注意 这里的right不是mid而是mid-1,因为如果是right=mid,当right-left=1的时候会陷入死循环*/
            }
            else//target>nums[mid]时,target下标在[mid+1,end]
            {
                left = mid + 1;/*注意:这里的begin不是mid而是mid+1*/
            }
        }
        return -1;
    }
};

总结:因为int类型的除法会直接舍去小数,这会导致一个问题,即我在后面每进行一次比较就习惯性的将区间界限值直接修改为mid(二分查找的思想就是这样的),但是在区间上下界差为1的情况下如果还未找到元素,程序将会陷入死循环。这也是初学者常犯的错误。

例如:left = 22;right=23;mid=22;

此时如果还未找到,那么无论执行mid = (left+right)/2多少次,mid都为22,陷入了死循环。

此外,在我们判断出除nums[mid]>target的情况下,我们就可以判断出target在[left,mid-1]中而不是[left,mid],nums[mid]已经判断过了,直接从比它前面一个的位置开始搜索即可。(小于也是同理,这里就不过多赘述了)

35.搜索插入位置

这一题只需要在上面的基础上增加一个如果没有找到指定数据,就返回应该插入的数据而不是返回-1

        //在没有找到的情况下,target的插入位置一定子mid的左边或者右边
        if (target > nums[mid])
        {
            return mid + 1;
        }
        else
        {
            return mid;
        }

34.查找指定元素起始位置

class Solution {

public:

    vector<int> searchRange(vector<int>& nums, int target) {

        int left = 0;

        int right = nums.size() - 1;

        vector<int> array = { -1,-1 };

        int mid;

        while ((array[0] == -1 || array[1] == -1) && left <= right)

        {

            mid = (left + right) / 2;

            if (nums[mid] == target)

            {

                array[0] = array[1] = mid;

               while ((array[0] - 1) >= 0&&nums[array[0] - 1] == target)

                {

                    array[0]--;

                }

                while ((array[1] + 1) <= (nums.size() - 1)&&nums[array[1] + 1] == target )

                {

                    array[1]++;

                }

                return array;

            }

            else if (target > nums[mid])

            {

                left = mid + 1;

            }

            else

            {

                right = mid - 1;

            }

        }

        return array;

    }

};

总结:这一题要注意数组越界访问,操作下标时要注意nums[-1]或nums[size]的情况出现,因此,找起始位置的那个while循环的循环条件中,array[0] - 1) >= 0要放在nums[array[0]-1]==target之前。

剩下两题  找平方根和判断完全平方数

    int mySqrt(int x) {
        int left = 0;
        int right = x;
        long long mid;
        while (left <= right)
        {
            mid = (left + right) / 2;
            if (mid*mid<=x&&(mid+1)*(mid+1)>x)
            {
                return mid;
            }
            else if ((mid + 1) * (mid + 1) <= x)
            {
                left = mid + 1;
            }
            else {
                right = mid - 1;
            }
        }
        return -1;

    }

bool isSqrt(int x) {
        int left = 0;
        int right = x;
        long long mid;
        while (left <= right)
        {
            mid = (left + right) / 2;
            if (mid * mid <= x && (mid + 1) * (mid + 1) > x)
            {
                if (mid * mid == x)
                {
                    return true;
                }
                else {
                    return false;
                }
            }
            else if ((mid + 1) * (mid + 1) <= x)
            {
                left = mid + 1;
            }
            else {
                right = mid - 1;
            }
        }
        return -1;

    }

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值