leedcode题解-二分查找

本文介绍了六道使用二分查找算法解决的LeetCode题目,包括求开方、寻找大于给定元素的最小字母、有序数组中单个元素、第一版错误、旋转数组最小数字以及查找区间的问题,通过比较和缩小搜索范围来实现解决方案。
摘要由CSDN通过智能技术生成

1、求开方

69. Sqrt(x) (Easy)

利用二分查找的思想,因为sqrt所在的区间肯定在1~x之间,又有sqrt==x/sqrt,sqrt=x/mid,通过比较sqrt与mid的大小,若mid>sqrt,往mid左边走,若mid较小,mid<sqrt往mid右边走,知道走到一个i的平方<x,i+1的平方>x的位置,此时end<start,跳出循环,end指向较小值,end为所求的值。

class Solution {
public:
    int mySqrt(int x) {
        if(x<=1)
            return x;
        int start=1;
        int end=x;
        while(start<=end){
            int mid=start+(end-start)/2;
            int sqrt=x/mid;
            if(sqrt==mid)
                return mid;
            else if(mid>sqrt)//mid较大,往左走
                end=mid-1;
            else
                start=mid+1;
        }
        return end;
    }
};

2. 大于给定元素的最小元素

744. Find Smallest Letter Greater Than Target (Easy)

class Solution {
public:
    char nextGreatestLetter(vector<char>& letters, char target) {
        if(letters.size()<2||target-'a'<0||target-'a'>25)
            return letters[0];
        int start=0;
        int end=letters.size()-1;
        while(start<=end){
            int mid=start+(end-start)/2;
            if(letters[mid]>target)
                end=mid-1;
            else
                start=mid+1;
        }
        if(start<letters.size())//判断是否越出边界,存在找不到字符的情况,这里需要注意
            return letters[start];
        else
            return letters[0];
    }
};

3、有序数组的 Single Element

540. Single Element in a Sorted Array (Medium)

思路,通过判断中位数的位置是奇数还是偶数,在容器中,偶数位置的左侧有偶数个数,奇数位置的左侧有奇数个数,由于数组中只有一个数没有成对,所以数组的长度为奇数。若mid为偶数,则左侧有偶数个数,判断mid是否与mid+1成对,若成对,则说明左侧的数都成对,则这个单一元素存在于mid的右侧,start=mid。若不成对,说明包括mid在内的左侧数有单一元素,end=mid;

若mid为奇数位置,则mid左侧有奇数个数,若mid与mid+1成对,则说明mid左侧存在单一元素,end=mid-1;若不成对,则说明mid与mid左侧的数成对,单一元素在右边,start=mid+1;

class Solution {
public:
    bool isvalid=true;
    int singleNonDuplicate(vector<int>& nums) {
        if(nums.empty()){
            isvalid=false;
            return 0;
        }
        int start=0;
        int end=nums.size()-1;
        while(start<end){
            int mid=start+(end-start)/2;
            if(mid%2==0){
                if(nums[mid]==nums[mid+1])
                    start=mid;
                else
                    end=mid;
            }
            else
            {  if(nums[mid]==nums[mid+1])
                   end=mid-1;
             else
                 start=mid+1;
        }
        }
        return nums[end];
        
    }
};

4、第一个错误的版本

278. First Bad Version (Easy)

// Forward declaration of isBadVersion API.
bool isBadVersion(int version);

class Solution {
public:
    int firstBadVersion(int n) {
        if(n<=0)
            return 0;
        int start=1;
        int end=n;
        while(start<end){//end=mid,则循环条件为start<end
            int mid=start+(end-start)/2;
            if(isBadVersion(mid))
                end=mid;//mid也为true,下一次遍历时也要把mid包含进去,mid可能是所求的位置
            else
                start=mid+1;
        }
        return start;
        
    }
};

 5、旋转数组的最小数字

153. Find Minimum in Rotated Sorted Array (Medium)

思路 通过比较mid与end的大小,逐步缩小范围。若mid位置的值大于end上的值,则最小值应该在mid的右侧,start=mid+1;若mid位置的值小于等于end位置上的值,则最小值应在包含mid向左的范围,end=mid;因此循环条件是start<end;

class Solution {
public:
    int findMin(vector<int>& nums) {
        int start=0;
           int end=nums.size()-1;
           while(start<end){
               int mid=start+(end-start)/2;
               if(nums[mid]>nums[end])
                   start=mid+1;
               else
                   end=mid;
           }
           return nums[start];
           }
};

6、查找区间

34. Search for a Range (Medium)

class Solution {
public:
    vector<int> searchRange(vector<int>& nums, int target) {
        vector<int>res;
        int l=0;
        int h=nums.size()-1;
        while(l<=h){
            int mid=l+(h-l)/2;
            if(nums[mid]>target)
                h=mid-1;
            else if(nums[mid]<target)
                l=mid+1;
            else if(nums[mid]==target){
                int flag1=mid;int flag2=mid;
                while(flag1>0&&nums[flag1-1]==target)//循环结束条件为mid为最左的target或mid=0
                    flag1--;
                while(flag2<nums.size()-1&&nums[flag2+1]==target)
                    ++flag2;
                res.push_back(flag1);
                res.push_back(flag2);
                return res;
            }
        }
        res.push_back(-1);
        res.push_back(-1);
        return res;
    }
};

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值