二分模板

二分模板一共有两个,分别适用于不同情况。
算法思路:假设目标值在闭区间[l, r]中, 每次将区间长度缩小一半,当l = r时,我们就找到了目标值。

版本1
当我们将区间[l, r]划分成[l, mid]和[mid + 1, r]时,其更新操作是r = mid或者l = mid + 1;,计算mid时不需要加1。

C++ 代码模板:
int bsearch_1(int l, int r)
{
    while (l < r)
    {
        int mid = l + r >> 1;
        if (check(mid)) r = mid;
        else l = mid + 1;
    }
    return l;
}
版本2
当我们将区间[l, r]划分成[l, mid - 1]和[mid, r]时,其更新操作是r = mid - 1或者l = mid;,此时为了防止死循环,计算mid时需要加1。

C++ 代码模板:
int bsearch_2(int l, int r)
{
    while (l < r)
    {
        int mid = l + r + 1 >> 1;
        if (check(mid)) l = mid;
        else r = mid - 1;
    }
    return l;
}

 

数的范围

https://www.acwing.com/problem/content/791/

import java.util.Scanner;

public class Main{
    public static void main(String[] args){
        Scanner scan = new Scanner(System.in);
        int n = scan.nextInt();
        int q = scan.nextInt();
        int a[] = new int [n];
        for(int i=0;i<n;i++){
            a[i] = scan.nextInt();
        }
        while(q-- > 0){
            int x = scan.nextInt();
            int l = 0, r = n-1;
            while(l<r){
                int mid = l + r >> 1;
                if(a[mid]>=x) r = mid;//找左边点--当mid大于等于x时,说明左边点肯定在左边的区间--r=mid
                else  l = mid +1;
            }
            if(a[l] != x) System.out.println("-1 -1");
            else{
                System.out.print(l+" ");
                l = 0;
                r = n - 1;
                while(l<r){
                    int mid  = l + r + 1>> 1;
                    if(a[mid]<=x)  l = mid;//找右边点--当mid小于等于x时,说明右边点肯定在右边的区间--l=mid;
                    else  r = mid -1;
                }
                System.out.println(r);
            }
        }
    }
}

 

搜索旋转排序数组

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

//先二分找到旋转点(两边的性质不同)
//再判断target在左边还是在右边
//最后二分找target下标
class Solution {
    public int search(int[] nums, int target) {
        if(nums.length == 0) return -1;
        int l = 0, r = nums.length-1;
        while(l<r){
            int mid = l + r + 1 >> 1;
            if(nums[mid]>=nums[0]) l = mid;
            else r = mid - 1;
        }
        
        if(target>=nums[0]) l =0;
        else{
            l = r + 1;
            r = nums.length-1;
        }

        while(l<r){
            int mid = l + r >> 1;
            if(nums[mid]>=target) r = mid;
            else l = mid + 1;
        }
        if(nums[r] == target) return r;
        else return -1;
    }
}

 

posted on 2020-07-07 16:41  qdu_lkc  阅读(163)  评论(0编辑  收藏  举报