二分法:夹缝中求和

题目:https://ac.nowcoder.com/acm/contest/8997/D

import java.util.*;
public class Main{
    static int[] a;
    public static void main(String[] args){
        Scanner in = new Scanner(System.in);
        int n = in.nextInt();
        int x = in.nextInt();
        int y = in.nextInt();
        a = new int[n];
        for(int i = 0; i<n; i++){
            a[i] = in.nextInt();
        }
        Arrays.sort(a);
        long result = 0;
        for(int i=0; i<a.length - 2; i++){
            long min = binarySearchMin(i+1, a.length, x-a[i]);
            long max = binarySearchMax(i+1, a.length, y-a[i]);
            result += max - min;
        }
        System.out.println(result);
    }

    private static int binarySearchMin(int begin, int end, int num){
        int left = begin;
        int right = end - 1;
        int min = end;
        while(left <= right){
            int mid = (left + right) / 2;
            if(a[mid] >= num){
                min = mid;
                right = mid - 1;
            }else{
                left = mid + 1;
            }
        }
        return min;
    }

    private static int binarySearchMax(int begin, int end, int num){
        int left = begin;
        int right = end - 1;
        int min = end;
        while(left <= right){
            int mid = (left + right) / 2;
            if(a[mid] > num){
                min = mid;
                right = mid - 1;
            }else{
                left = mid + 1;
            }
        }
        return min;
    }
}

首先看标题就知道,二分法,数据结构没有好好听,所以呢,做起来就非常的苦难了。再次复习时,也一定要再次复习二分法的方法,借鉴别人的代码时发现,我们要找出下界和上界,在找出这两个之后,还要考虑,这两个数是否有重复的,难点就在这里,我们要利用二分法找出下界最左边的数,以及上界最右边的数,别人的经验非常丰富,以至于自己看了半天(废话少说)。别的代码不多做解释,因为要自己在回来看的时候要再多多理解一下代码。方法名(开始,结束,关键数),那么每次方法开始,开始和结束都是一样的,只有关键数,找下界的关键数是用x-a[i],那么找上界的关键数是用y-a[i],这样很巧妙,至于为什么,反正我只学会了 二分查找(进阶的)。

 private static int binarySearchMax(int begin, int end, int num){
        int left = begin;
        int right = end - 1;
        int min = end;
        while(left <= right){
            int mid = (left + right) / 2;
            if(a[mid] > num){
                min = mid;
                right = mid - 1;
            }else{
                left = mid + 1;
            }
        }
        return min;
    }

二分查找(进阶):
以:1 1 1 2 2 2 3 3 4 4 4 5 6 7 7为例
首先找下界时,数组左右分别为begin和end,那么关键数为num,例如num=1时,开始循环,mid = 0+14,mid=7,也就是3,在循环之后呢,会来到left=a[0],right=a[1],那么这个时候mid=0,那么a[mid]就是最小最左边的数了。
寻找上界的时候,num=y-a[i],num=3,那么mid=7,此时不是最右边的上界,那么就开始循环,不大于num则左边+1,但是呢mid还是7,继续+1,那么mid=8,a[mid]=4,那么就大于了3,此时继续循环就可以一直进行到结束,而right都不动。

全部评论

相关推荐

05-14 20:34
门头沟学院 Java
窝补药贝八股:管他们,乱说,反正又不去,直接说680
点赞 评论 收藏
分享
求面试求offer啊啊啊啊:这个在牛客不是老熟人了吗
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务