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);
}
}