LeetCode刷题记录.Day1

二分查找基础:

二分查找

题目链接 Loading Question... - 力扣(LeetCode)

最开始的题解:

class Solution {
public:
    int search(vector<int>& nums, int target) {
        int left = 0 ;
        int right = nums.size() ;
        if (left < right){
            while(left < right){
                int middle = (left + right) / 2 ;
                if(nums[middle] > target){
                    right = middle ;
                }
                else if(nums[middle] < target){
                    left = middle ;
                }
                else if(nums[middle] == target){
                    return middle ;
                }
            }
            return -1 ;
        }
        else{
            return -1 ;
        }

    }
};

提交结果是超出时间限制。

在本地调试执行后发现是对边界理解有问题。左右边界在此时必不会有 = middle的情况,本来搜索范围在闭区间里,实际上我的循环更新边界,更新后的边界都在区间外,更新后的区间实际上是个开区间,但是循环条件确是闭区间。所以肯定会死循环。

我这种写法会导致如果target为数组中缺失数,出现middle不为整数的情况,导致进入死循环,所以超出时间限制。

 修改后

 

class Solution {
public:
    int search(vector<int>& nums, int target) {
        int left = 0 ;
        int right = nums.size() - 1 ;
        if (target > nums[right] || target < nums[left]){
            return -1 ;
        }
        if (left <= right){
            while(left <= right){
                int middle = left + (right - left) / 2 ;
                if(nums[middle] > target){
                    right = middle - 1;
                }
                else if(nums[middle] < target){
                    left = middle + 1;
                }
                else if(nums[middle] == target){
                    return middle ;
                }
                else {
                    return -1 ;
                }
            }
            return -1 ;
        }
        else{
            return -1 ;
        }

    }
};

考虑了题目情况,数组为顺序排列。如果target大于数组边界值或小于数组边界值,可以直接返回 -1而不用进行二分查找。

最后根据标准解题方法过了一遍。

class Solution {
public:
    int search(vector<int>& nums, int target) {
        int left = 0 ;
        int right = nums.size() - 1 ;
        while(left <= right){
            int middle = left + (right - left) / 2;
            if(target > nums[middle]){
                left = middle + 1;
            }
            else if(target < nums[middle]){
                right = middle - 1;
            }
            else{
                return middle;
            }
        }
        return -1;

    }
};

 个人理解的重点在边界条件判断,不管是循环条件还是更新区间,必须符合区间定义。称之为循环不变量。

搜索插入位置

题目链接 35. 搜索插入位置 - 力扣(LeetCode)

    int search(vector<int>& nums, int target) {
        int left = 0 ;
        int right = nums.size() - 1 ;
        if (target <= nums[left])
        {
            return left ;
        }
        if (target > nums[right]){
            return right + 1 ;
        }
        else if (target == nums[right])
        {
            return right ;
        }
        

        

        while(left <= right){
            int middle = left + (right - left) / 2 ;
            if(nums[middle] > target){
                right = middle - 1;
            }
            else if(nums[middle] < target){
                left = middle + 1;
            }
            else if(nums[middle] == target){
                return middle ;
            }
        }
        return left ;

    }

主要重点在于理解边界条件的判断。我这个写法有点冗余了.

 

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

题目链接 34. 在排序数组中查找元素的第一个和最后一个位置 - 力扣(LeetCode)

class Solution {
public:
    vector<int> searchRange(vector<int>& nums, int target) {
        int leftBorder = getLeftRange(nums, target);
        int rightBorder = getRightRange(nums, target);
        if (leftBorder == -2 || rightBorder == -2) return {-1,-1};
        if (rightBorder - leftBorder > 1) return {leftBorder + 1, rightBorder - 1};
        return {-1, -1};
    }
private:
    int getLeftRange(vector<int>& nums, int target) {
        int left = 0 ;
        int right = nums.size() - 1 ;
        int leftBorder = -2 ;
        while(left <= right){
            int middle = left + (right - left) / 2 ;
            if(nums[middle] >= target){
                right = middle - 1;
                leftBorder = right;
            }
            else{
                left = middle + 1;
            }
        }
        return leftBorder;
 
    }

    int getRightRange(vector<int>& nums, int target) {
        int left = 0 ;
        int right = nums.size() - 1 ;
        int rightBorder = -2 ;
        while(left <= right){
            int middle = left + (right - left) / 2 ;
            if(nums[middle] > target){
                right = middle - 1;
            }
            else{
                left = middle + 1;
                rightBorder = left;
            }
        }
        return rightBorder;
    }
};

修改出来的标准写法。不过还是没有理解为什么要这样去找左右边界。需要下来继续研究吃透这题的原理。

posted @ 2022-10-30 23:48  凱風快晴  阅读(23)  评论(0)    收藏  举报