做题总结(二分查找相关)题目704、35、34

704. 二分查找

使用二分查找的前提是(1)数组为有序数组(2)数组中无重复元素
注意边界条件是 while(left <= right) 还是 while(left <right)
请参考代码随想录

https://programmercarl.com/0704.%E4%BA%8C%E5%88%86%E6%9F%A5%E6%89%BE.html#%E6%80%BB%E7%BB%93

35. 搜索插入位置

运行成功。

class Solution {
public:
    int searchInsert(vector<int>& nums, int target) {
        int low=0;
        int high=nums.size()-1;
        int mid;
        if(target > nums[high]) return (high+1);
        if(target < nums[low]) return 0;
        while(low <= high) {//ERROR:条件写错,这里是小于等于
            mid = (low + high)/2;
            if(nums[mid] == target) {
                return mid;
            }
            else if(nums[mid] > target) {
                high = mid - 1;
            }
            else if(nums[mid] < target) {
                low = mid + 1;
            }
        }
        return low;

    }
};

要点
返回值究竟是low还是high
如果数组中没有target,那么跳出循环前的一步 mid=low=high
(1)如果 target>nums[mid], low=mid+1
target 的位置在右侧,正好是low
(2)如果 target<nums[mid],high=mid-1
target 的位置就是 mid 这个位置(这里有个隐含条件是 target 比 nums[mid-1] 大)。
在这里插入图片描述

34. 在排序数组中查找元素的第一个和最后一个位置

想法:数组nums是有序数组,且要求查找时间复杂度为 O(log n)。因此可以用二分查找,但是因为nums中元素重复,查找到的下标只有一个,所以设置left、right指针,分别往前往后找边界。

class Solution {
public:
    vector<int> searchRange(vector<int>& nums, int target) {
        int low,high,mid;
        low = 0;
        high = nums.size()-1;
        int tnum;
        int tpos = -1;
        while(low <= high) {
            mid = (low + high)/2;
            tnum = nums[mid]; 
            if(target == tnum) {
                tpos = mid;
                break;
            }
            else if(target > tnum) {
                low = mid + 1;
            }   
            else if(target < tnum) {
                high = mid - 1;
            }    
        }

        vector<int> ans;
        if(tpos == -1) {
            ans.push_back(-1);
            ans.push_back(-1);
            return ans;
        }

        int left = tpos,right = tpos;
        while(nums[left] == target) {
            left--;
        }
        left++;

        while(nums[right] == target) {
            right++;
        }
        right--;

        ans.push_back(left);
        ans.push_back(right);

        return ans;
        
    }
};

报错

Line 1037: Char 34: runtime error: addition of unsigned offset to 0x602000000430 overflowed to 0x60200000042c (stl_vector.h)
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior /usr/bin/…/lib/gcc/x86_64-linux-gnu/11/…/…/…/…/include/c++/11/bits/stl_vector.h:1046:34

8 / 88 个通过的测试用例

在这里插入图片描述
错误原因:数组下标越界,当满足 nums[0] == target时,进入循环,left-- = -1。下一个循环进入判断,nums[-1] 超出数组边界。
同理,nums[right]也要考虑 right不超过nums数组的大小。

        while(nums[left] == target) {
            left--;
        }
        left++;

修改如下图

        int left = tpos,right = tpos;
        while(left >= 0 && nums[left] == target) {
            left--;
        }
        left++;

        while(target < nums.size() && nums[right] == target) {
            right++;
        }
        right--;

报错:解答错误

28 / 88 个通过的测试用例

在这里插入图片描述

这里是while写错了 while( right < nums.size() && nums[right] == target)

再次修改如下图

class Solution {
public:
    vector<int> searchRange(vector<int>& nums, int target) {
        int low,high,mid;
        low = 0;
        high = nums.size()-1;
        int tnum;
        int tpos = -1;
        while(low <= high) {
            mid = (low + high)/2;
            tnum = nums[mid]; 
            if(target == tnum) {
                tpos = mid;
                break;
            }
            else if(target > tnum) {
                low = mid + 1;
            }   
            else if(target < tnum) {
                high = mid - 1;
            }    
        }

        vector<int> ans;
        if(tpos == -1) {
            ans.push_back(-1);
            ans.push_back(-1);
            return ans;
        }

        int left = tpos,right = tpos;
        while(left >= 0 && nums[left] == target) {
            left--;
        }
        left++;

        while(right < nums.size() && nums[right] == target) {
            right++;
        }
        right--;

        ans.push_back(left);
        ans.push_back(right);

        return ans;
        
    }
};

运行成功
在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值