leetcode刷题——算法(4):二分查找

二分查找

寻找一个数(基本的二分搜索)

因为我们初始化 right = nums.length - 1

所以决定了我们的「搜索区间」是 [left, right]

所以决定了 while (left <= right),同时也决定了 left = mid+1 和 right = mid-1

 

因为我们只需找到一个 target 的索引即可,所以当 nums[mid] == target 时可以立即返回

int binarySearch(vector<int> nums,int key){

         int left=0,right=nums.size()-1;  //**

         while(left<=right){     //**

                   int mid=left+(right-left)/2;

                   if(nums[mid]<key)

                            left=mid+1;

                   else if(nums[mid]>key)

                       right=mid-1;

                   else

                       return mid;

         }

         return -1;

}

寻找左侧边界的二分搜索

因为我们初始化 right = nums.length

所以决定了我们的「搜索区间」是 [left, right)

所以决定了 while (left < right)

同时也决定了 left = mid+1 和 right = mid

 

因为我们需找到 target 的最左侧索引 所以当 nums[mid] == target 时不要立即返回 而要收紧右侧边界以锁定左侧边界

int binarySearchFirst(vector<int> nums,int key){

         int left=0,right=nums.size();  //**

         while(left<right){   //**

                   int mid=left+(right-left)/2;

                   if(nums[mid]>=key){

                            right=mid;

                   }else

                       left=mid+1;

         }

         return left;

}

寻找右侧边界的二分查找

因为我们初始化 right = nums.length

所以决定了我们的「搜索区间」是 [left, right)

所以决定了 while (left < right)

同时也决定了 left = mid+1 和 right = mid

 

因为我们需找到 target 的最右侧索引

所以当 nums[mid] == target 时不要立即返回

而要收紧左侧边界以锁定右侧边界

又因为收紧左侧边界时必须 left = mid + 1

所以最后无论返回 left 还是 right,必须减一

int binarySearchLast(vector<int> nums,int key){

         int left=0,right=nums.size();

         while(left<right){   //**

                   int mid=left+(right-left)/2;

                   if(nums[mid]<=key){

                            left=mid+1;  

                   }else right=mid;

         }

         return left-1;

}

//相当于查找第一个>key的下标,然后-1。

二分查找(2.15)

 

 

1. 求开方

一开始未做出,多种解法

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

类上,Ok

 

3. 有序数组的 Single Element

Ok,二分法思考后做出

4. 第一个错误的版本

Ok

 

5. 旋转数组的最小数字

一开始未做出

6. 查找区间

一次修改后ok

 

1. 求开方

69. Sqrt(x) (Easy)

https://leetcode-cn.com/problems/sqrtx/submissions/

  1. 二分法:查找最后一个数满足(mid*mid<=n),即查找第一个数满足mid*mid>n然后-1
    class Solution {
    public:
        int mySqrt(int x) {
            if(x<0) return -1;
            else if(x==0||x==1) return x;
            int left=1,right=x;
            while(left<right){
                int mid=left+(right-right)/2;
                if(x/mid>=mid) left=mid+1;
                else right=mid;
            }
            return left-1;
        }
    };
    //查找第一个>x,然后-1
    
  2. 袖珍计算机算法:时间复杂度O(1),空间复杂度O(1)

class Solution {
public:
    int mySqrt(int x) {
        if(x<=1) return x;
        int left=exp(0.5*log(x));
        int right=left+1;
        if(x/right<right) return left;
        else return right;        
    }
};

3. 递归:时间复杂度O(logN),空间复杂度O(logN)

class Solution {
public:
    int mySqrt(int x) {
        if(x<=1) return x;
        int left=mySqrt(x>>2)<<1;
        int right=left+1;
        if(x/right<right) return left;
        else return right;        
    }
};

4. 牛顿法:时间复杂度O(logN),空间复杂度O(1)

class Solution {
public:
    int mySqrt(int x) {
        if(x<=1) return x;
        double x0=x;
        double x1=(x0+x/x0)/2;
        while(abs(x1-x0)>=1){
            x0=x1;
            x1=(x0+x/x0)/2;
        }
        return (int)x1;
    }
};

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

744. Find Smallest Letter Greater Than Target (Easy)

https://leetcode-cn.com/problems/find-smallest-letter-greater-than-target/submissions/

类上,查找第一个大于给定元素

3. 有序数组的 Single Element

540. Single Element in a Sorted Array (Medium)

https://leetcode-cn.com/problems/single-element-in-a-sorted-array/

1.	异或
class Solution {
public:
    int singleNonDuplicate(vector<int>& nums) {
        int res=0;
        for(int i=0;i<nums.size();i++)
            res^=nums[i];
        return res;
    }
};

2.	二分排序
class Solution {
public:
    int singleNonDuplicate(vector<int>& nums) {
        int n=nums.size();
        int left=0,right=n-1;
        while(left<=right){
            int mid=(left+right)/2;
            bool isEven=mid%2;
            if(mid+1<n&&nums[mid]==nums[mid+1]){
                if(isEven)  right=mid-1;
                else  left=mid+2;
            }else if(mid-1>=0&&nums[mid]==nums[mid-1]){
                if(isEven)  left=mid+1;
                else right=mid-2;                 
            }else return nums[mid];
        }
        return nums[right];
    }
};

4. 第一个错误的版本

278. First Bad Version (Easy)

https://leetcode-cn.com/problems/first-bad-version/

*找中间数用int mid=left+(right-left)/2;

5. 旋转数组的最小数字

153. Find Minimum in Rotated Sorted Array (Medium)

https://leetcode-cn.com/problems/find-minimum-in-rotated-sorted-array/

class Solution {
public:
    int findMin(vector<int>& nums) {
        int left=0,right=nums.size()-1;
        while(left<right){
            int mid=left+(right-left)/2;
            if(nums[mid]<nums[right]) right=mid;
            else left=mid+1;
        }
        return nums[left];
    }
};
//找第一个小于右边

6. 查找区间

34. Find First and Last Position of Element in Sorted Array

https://leetcode-cn.com/problems/find-first-and-last-position-of-element-in-sorted-array/

一次修改后ok

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值