Leetcode中的二分算法

Leetcode中有很多衍变的二分查找算法问题。本质上都是讲问题逐步分解成更小的问题,然后求得问题的解。


题目一:Pow(x, n)

Implement pow(x, n)

思路:pow(x, n)操作就是将x与自己相乘n变,如果用重复n次循环,则可能会TLE, 比如[0.0001, 213783647]。那么如何加速这个过程呢?这里需要利用递归算法。

class Solution {
public:
    double pow(double x, int n) {
        if(n==0) return 1;
        if(n==1) return x;
        int exp = n<0?-n:n; //先把符号统一成正好
        double result= exp%2==0?pow(x*x,exp/2):pow(x*x,exp/2)*x;
        return n<0?1/result:result;
    }
};
说明:像这样的算术运算都要主要符号问题。此外还有溢出问题。

题目二:Sqrt(x)

Implement int sqrt(int x). Compute and return the square root of x.

思路:这道题参照着网上流传的binary search模板写的,start=-1,  end=n+1, 模板挺有意思的,没有==跳出的情况,唯一结束的条件是end-start>1不成立。当然最重要的是,还是啥不变式,这里是是  start<=sqrt<end !

    class Solution {  
    public:  
        int sqrt(int x) {  
            // Start typing your C/C++ solution below  
            // DO NOT write int main() function  
            long long int start = -1;  
            long long int end = (long long int)x+1;  
             
            while (end - start > 1) {  
                long long int mid = (end - start) / 2 + start;  
                if (mid*mid > x) {  
                    end = mid;  
                } else {  
                    start = mid;  
                }            
            }  
            return start;  
        }  
    };  

题目三:Search Insert Position

Given a sorted array and a target value, return the index if the target is found. If not, return the index where it would be if it were inserted in order. For example, [1,3,5,6], 5->2   [1,3,5,6], 2->1

思路:最直接的方法就是从左到右的遍历,遇到了就返回index,否则返回要插入的问题。但是由于这里是有序的,可以使用更有效的二分搜索算法。仿照上面得算法得到

class Solution {
public:
    int searchInsert(int A[], int n, int target) {
        if(n==0) return 0;
        int start=-1, end=n;
        while(end-start>1){
            int mid=(end+start)/2;
            if(target<A[mid]) end=mid;
            else start=mid;
        }
        if(start>=0&&A[start]==target) return start;
        return start+1;
    }
};

题目三:Search in Rotated Sorted Array

Suppose a sorted array is rotated at some pivot unknown to you beforehand, i.e., 0 1 2 4 5 6 7 might become 4 5 6 7 0 1 2, You are given a target value to search. If found in the array return its index, otherwise return -1. You may assume no duplicate exists in the array.

思路:虽然没有完全有序,但是还是有规律的。这里的二分查找略需要改造下。在查找前需要判定目前在那一段中,保证有序区中查找。

class Solution {
public:
    int search(int A[], int n, int target) {
        int low=0;
        int high=n-1;
        while(low<=high){   //是有挪动的情况
            int mid=(low+high)/2;
            if(A[mid]==target) return mid;
            if(A[low]<=A[mid]){           //前半部分是升序的
                if(A[mid]<target) low=mid+1; 
                else if(target>=A[low]) high=mid-1;
                else low=mid+1;
            }                             //后半部分是升序的
            else if(A[mid]>target) high=mid-1;
            else if(A[high]>=target) low=mid+1;
            else high=mid-1;
        }
        return -1;
    }
};

题目四:Search in Rotated Sorted Array II

Follow up for "Search in Rotated Sorted Array": What if duplicates are allowed? Would this affect the run-time complexity? How and why?

思路:得额外增加一个判断重复的代码

class Solution {
public:
    bool search(int A[], int n, int target) {
        if(n==0 || A==NULL) return false;
        return doSearch(A, target, 0, n-1);
    }
    
    bool doSearch(int A[], int target, int low, int high){
        while(low<=high){
            int mid=low+(high-low)/2;
            if(A[mid]==target) return true;
            //what abount duplicates
            if(A[low]==A[mid]&&A[mid]==A[high]){ //先判断重复
                for(int i=low; i<=high; i++)
                    if(A[i]==target) return true;
                return false;
            }
            //
            if(A[low]<=A[mid]){
                if(A[mid]<target) low=mid+1;
                else if(A[low]<=target) high=mid-1;
                else low=mid+1;
            }
            else{ 
                if(target<A[mid]) high=mid-1;
                else if(target<=A[high]) low=mid+1;
                else high=mid-1;
            }
        }
        return false;
    }
};


题目五: Search for a Range

Given a sorted array of integers, find the starting and ending position of a given target value. Your algorithm's runtime complexity must be in the order of O(logn). If the target is not found in the array, return [-1, -1].  For example, given [5, 7, 7, 8, 8, 10] and target value 8, return [3, 4]

思路:还是和上面的题目类似,最直接的方法就是暴力查找。

vector<int> searchRange(int A[], int n, int target) {
        int start, end;
        start=end=-1;
        vector<int> res;
        
        for(int i=0;i<n;i++){
            if(A[i]==target){ 
                start=i;
                while(i<n&&A[i]==target) i++;
                end=i-1;
                break;
            }
        }
        res.push_back(start);
        res.push_back(end);
        return res;
    }

改进的方法则是通过两次 二分查找方法分别找到range的start和end

vector<int> searchRange(int A[], int n, int target) {
        vector<int> range(2, -1);
        int lower = 0;
        int upper = n;
        int mid;
 
        // Search for lower bound
        while (lower < upper) {    //这里只能是小于号,不能是<=, 否则出现死循环
            mid = (lower + upper) / 2;
            if (A[mid] < target)   
                lower = mid + 1;
            else                   
                upper = mid;
        }
 
        // If the target is not found, return (-1, -1)
        if (A[lower] != target)
            return range;
        range[0] = lower;
 
        // Search for upper bound
        upper = n;
        while (lower < upper) {
            mid = (lower + upper) / 2;
            if (A[mid] > target)
                upper = mid;
            else
                lower = mid + 1;  
        }
        range[1] = upper - 1;
 
        return range;
    }



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值