Arrays.binarySearch 详解

Arrays.binarySearch 详解

前提:非降序排序数组

binarySearch(Object[] a, Object key)

  • a:待搜索的数组
  • key:要搜索的值
    逻辑条件
  • 可以找到:返回一个 >=0 的索引
  • 找不到:【从 1 开始计数】
    • 在数组范围内,返回 -(key 将要插入的位置)
    • 不在范围内:返回 -1 或者 -(len + 1)

应用

240. 两数之和绝对值最小【注意点:Math.abs的括号位置】

import java.util.Scanner;
import java.util.*;

// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        String[] split = in.nextLine().split(" ");
        int len = split.length;
        int[] arr = new int[len];
        for (int i = 0; i < len; i++) {
            arr[i] = Integer.parseInt(split[i]);
        }
        int index = Arrays.binarySearch(arr, 0);
        if (index < 0){
            index = -index - 1;
        }
        if (index == 0){   // 0超过了左侧边界、0恰好在第一个位置
            System.out.println(Math.abs(arr[0] + arr[1]));
            return;
        }
        if (index >= len - 1){    // len - 1:0在最后一个位置 len:超出右侧界限
            System.out.println(Math.abs(arr[len - 1] + arr[len - 2]));
            return;
        }
        //  范围之内
        //  [0, index - 1]:负数
        //  [index, len - 1]:非负数
        int res = Integer.MAX_VALUE;
        if (index >= 2){
            res = Math.min(res, Math.abs(arr[index - 1] + arr[index - 2])); //  负数的末尾2个!!!
        }
        if (index < len - 1){
            res = Math.min(res, Math.abs(arr[index] + arr[index + 1])); //  非负数的头 2个!!!
        }
        //  将非负数部分截断出来
        int[] right = Arrays.copyOfRange(arr, index, len);  //  不包含末尾!!!

        for (int i = 0; i < index; i++) {// 用负数一个一个去比较
            int tempIndex = Arrays.binarySearch(right, -arr[i]); //  【负数的模】 在右侧中的位置
            if (tempIndex >= 0 && tempIndex <= right.length - 1){
                System.out.println(0);
                return; //  能找到说明已经为 0 了,返回就行了
            }
            //  找不到 【tempIndex - 1】 【带插入的】 【tempIndex】
            if (tempIndex < 0){
                tempIndex = -tempIndex - 1;
            }

            if (tempIndex == right.length){  //  超出右界的情况!!!
                tempIndex = right.length - 1;
            }
            res = Math.min(res, Math.abs(right[tempIndex] + arr[i]));
            if (tempIndex >= 1){
                res = Math.min(res, Math.abs(right[tempIndex - 1] + arr[i]));
            }
        }
        System.out.println(res);
  }
}

238. 乱序正数序列两数之和绝对值最小

import java.util.Scanner;
import java.util.*;


// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    static int[] arr;
    static int leftNum;
    static int rightNum;
    static int res = Integer.MAX_VALUE;

    public static void main(String[] args) {
         Scanner in = new Scanner(System.in);
        String[] split = in.nextLine().split(" ");
        int len = split.length;
        arr = new int[len];
        for (int i = 0; i < len; i++) {
            arr[i] = Integer.parseInt(split[i]);
        }
        Arrays.sort(arr);   //  排序
        int index = Arrays.binarySearch(arr, 0);
        if (index < 0){
            index = -index - 1;
        }
        if (index == 0){
            leftNum = arr[0];
            rightNum = arr[1];
            res = getAbs(leftNum, rightNum);
            System.out.println(leftNum + " " + rightNum + " " + res);
            return;
        }
        if (index >= len - 1){
            leftNum = arr[arr.length - 2];
            rightNum = arr[arr.length - 1];
            res = getAbs(leftNum, rightNum);
            System.out.println(leftNum + " " + rightNum + " " + res);
            return;
        }

        //  左侧:[0, index - 1]:负数
        //  右侧:[index, len - 1]
        int[] right = Arrays.copyOfRange(arr, index, len);
        for (int i = 0; i < index; i++) {
            int tempIndex = Arrays.binarySearch(right, -arr[i]);
            if (tempIndex >= 0 && tempIndex < right.length){
                leftNum = arr[i];
                rightNum = right[tempIndex];
                res = getAbs(leftNum, rightNum);
                System.out.println(leftNum + " " + rightNum + " " + "0");
                return;
            }
            if (tempIndex < 0){
                tempIndex = -tempIndex - 1;
            }
            //  tempIndex - 1、待插入位置、tempIndex
            if (tempIndex == right.length){
                tempIndex = right.length - 1;
            }

            if (getAbs(arr[i], right[tempIndex]) < res){  //  【arr[i]、right[tempIndex]】
                leftNum = arr[i];
                rightNum = right[tempIndex];
                res = getAbs(leftNum, rightNum);
            }

            if (tempIndex >= 1){
                if (getAbs(arr[i], right[tempIndex - 1]) < res){  //  【arr[i]、right[tempIndex - 1]】
                    leftNum = arr[i];
                    rightNum = right[tempIndex - 1];
                    res = getAbs(leftNum, rightNum);
                }
            }

        }
        System.out.println(leftNum + " " + rightNum + " " + res);
    }

     public static int getAbs(int i, int j){
        return Math.abs(i + j);
    }
}

330. 排队游戏【注意:二分查找要先排序】

import java.util.Scanner;
import java.util.*;


// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    public static void main(String[] args) {
        ArrayList<Integer> list = new ArrayList<>();
        Scanner in = new Scanner(System.in);
        String s = in.nextLine();
        String[] split = s.split(" ");
        int count = Integer.parseInt(split[0]);
        int specialCount = Integer.parseInt(split[1]);
        int[] special = new int[specialCount];
        int k = Integer.parseInt(split[2]);
        boolean[] flag = new boolean[count];
        String[] temp = in.nextLine().split(" ");
        for (int i = 0; i < specialCount; i++) {
            flag[Integer.parseInt(temp[i])] = true;
        }
        String s1 = in.nextLine();
        String[] split1 = s1.split(" ");
        int[] arr = new int[split1.length];
        int specialIndex = 0;
        for (int i = 0; i < arr.length; i++) {
            int anInt = Integer.parseInt(split1[i]);
            if (flag[i]){
                special[specialIndex++] = anInt;
            }
            arr[i] = anInt;
        }
        int res = 0;
        for (int i = 0; i < count; i++) {
            if (flag[i]){
                list.add(arr[i]);
                continue;
            }
            Collections.sort(list);  //  二分查找要先排序
            int index = Collections.binarySearch(list, arr[i]);
            if (index < 0){
                index = -index - 1;  //  负数的处理方式
            }else{
                 while (index < list.size() - 1 && arr[i] == list.get(index + 1)){  //  最后出现的位置
                    index++;
                }
                index++;  // 正数:要 + 1
            }
            res += list.size() - index;
            
        }
        if (res > k){
            System.out.println(1);
            return;
        }
        System.out.println(0);
    }
}
posted @ 2023-09-22 11:41  爱新觉罗LQ  阅读(805)  评论(0编辑  收藏  举报