1.在一个有序的数组中,查找某一个数是否存在
2.在一个有序的数组中,查找>=2的最左侧位置
3.找到一个局部最小值
在一个有序的数组中,查找某一个数是否存在
找num是否存在 先找一个中间位置 middleIndex middleIndex==num 存在 middleIndex>num 右边一定没有num,可能在左边存在num middleIndex<num 左边一定没有num,可能在右边存在num 如此往复,指导剩下最后一个数没办法再二分
package com.ss.sort;import java.util.Arrays;import java.util.Random;/*** <p>* 在一个有序的数组中,查找某一个数是否存在* </P>** @author: zhangss* @since: 2021-01-05**/public class BinarySearchExist {public static boolean exist(int[] arr, int num){if(null == arr || arr.length < 1){return false;}if(arr.length == 1 && arr[0] == num){return true;}int l = 0, r = arr.length - 1, mid;while (l < r) {mid = l + (r - l) / 2;if(arr[mid] == num){return true;}else if(arr[mid] > num){r = mid - 1;}else{l = mid + 1;}}return arr[l] == num;}public static boolean comparator(int[] arr, int num){return exist(arr, num) == Arrays.binarySearch(arr, num) >= 0;}/*** 产生有序数组* @return*/public static int[] getSortedArr(){Random random = new Random();// 若电脑性能有限,生成的数组可以降低长度int length = random.nextInt(10);int[] arr = new int[length];for(int i = 0; i < length; i++){arr[i] = random.nextInt(100);}Arrays.sort(arr);return arr;}public static void main(String[] args) {for (int i = 0; i < 50; i++) {Random random = new Random();int[] arr = getSortedArr();int num = random.nextInt(100);if(!comparator(arr, num)){System.out.println("第" + (i + 1) + "次");System.out.println(Arrays.toString(arr));System.out.println("num: " + num);System.out.println("失败\n");}}}}
在一个有序的数组中,查找>=2的最左位置
找num的最左位置 找到中间位置mid, 初始化最左侧位置leftIndex = -1 mid = 2 leftIndex = mid 左边可能有=2的最左位置, 继续找左边 mid > 2 leftIndex = mid 左边可能有=2的最左位置, 继续找左边 mid < 2 右边可能有最左侧位置,继续找右边
package com.ss.sort;import java.util.Arrays;import java.util.Random;/*** <p>* 在一个有序的数组中,查找>=2的最左位置* </P>** @author: zhangss* @since: 2021-01-05**/public class BinarySearchNearLeft {public static int nearLeft(int[] arr, int num){if(null == arr || arr.length < 1){return -1;}if(arr.length == 1 && arr[0] >= num){return 0;}int l = 0, r = arr.length - 1, mid = 0, leftIndex = -1;while (l <= r){mid = l + (r - l) / 2;if(arr[mid] >= num){leftIndex = mid;r = mid - 1;}else{l = mid + 1;}}return leftIndex;}public static int comparator(int[] arr, int num) {int leftIndex = -1;for (int i = 0; i < arr.length; i++) {if (arr[i] >= num) {leftIndex = i;break;}}return leftIndex;}/*** 产生有序数组* @return*/public static int[] getSortedArr(){Random random = new Random();// 若电脑性能有限,生成的数组可以降低长度int length = random.nextInt(5);length = length < 2 ? 2 : length;int[] arr = new int[length];for(int i = 0; i < length; i++){arr[i] = random.nextInt(10);}Arrays.sort(arr);return arr;}public static void main(String[] args) {Random random = new Random();for (int i = 0; i < 50000; i++) {int[] sortedArr = getSortedArr();int numIdx = Math.abs(random.nextInt(sortedArr.length - 1));int i1 = nearLeft(sortedArr, sortedArr[numIdx]);int i2 = comparator(sortedArr, sortedArr[numIdx]);if(i1 != i2){System.out.println(Arrays.toString(sortedArr));System.out.println(sortedArr[numIdx]);System.out.println("failed");}}}}
找到一个局部最小值
局部最小值: 最左边的值小,比右边的值大,就是局部最小值 1.第一个位置上的数。[0]<[1] 就直接是局部最小 2.最后一个位置上的书 [n-1] > [n] 就直接是局部最小 3.[i-1]>[i] && [i+1]>[i] 这样的数就是局部最小值 先判断第一个数、最后一个数是不是局部最小值,是的话就直接找到了,返回该值
minIdx = -1 二分查找,找到中间位置mid [mid] < [mid-1] && [mid] < [mid] + 1 说明这个值就是局部最小,那就不用再找了 [mid-1] < [mid] < [mid + 1] 说明左边必有局部最小 [mid-1] > [mid] > [mid + 1] 说明右边必有局部最小 找到一个就返回
package com.ss.sort;import java.util.Arrays;import java.util.Random;/*** <p>* 找到一个局部最小值* </P>** @author: zhangss* @since: 2021-01-05**/public class BinarySearchAwesome {/*** 找到一个局部最小值的下标* @param arr* @return*/public static int getLessIndex(int[] arr){if(null == arr || arr.length < 1){return -1; // not exist}if(arr.length > 1 && arr[0] < arr[1]){return 0;}if (arr.length > 1 && arr[arr.length - 1] < arr[arr.length - 2]) {return arr.length - 1;}// 第一个和最后一个都不是局部最小,所以第一个和最后一个都不检查了int l = 1, r = arr.length - 2, midIdx = -1;while (l <= r){midIdx = l + (r - l) / 2;if (arr[midIdx] < arr[midIdx + 1]) {r = midIdx - 1;} else if (arr[midIdx] > arr[midIdx + 1]) {l = midIdx + 1;} else {return midIdx;}}return l;}/*** 生成测试数据* 无序,不重复* @return*/public static int[] getArr(){Random random = new Random();int[] arr = {};for (int num = 0; num < random.nextInt(100); num++){int length = random.nextInt(10);length = length > 1 ? length : 2;int[] tempArr = new int[length];for (int i = 0; i < tempArr.length; i++) {tempArr[i] = random.nextInt(100);}tempArr = Arrays.stream(tempArr).distinct().sorted().toArray();if(random.nextInt(1000)%2 == 0){tempArr = reverse(tempArr);}arr = Arrays.copyOf(arr, arr.length + tempArr.length);for(int i = arr.length - tempArr.length, j = 0; i < arr.length; i++, j++){arr[i] = tempArr[j];}}arr = Arrays.stream(arr).distinct().toArray();return arr;}/*** 反转数组* @param arr* @return*/public static int[] reverse(int[] arr){int[] newInt = new int[arr.length];for (int i = newInt.length - 1, j = 0 ; i > -1; i--, j++) {newInt[j] = arr[i];}return newInt;}/*** 测试50w次,确认方法没问题* @param args*/public static void main(String[] args) {for (int i = 0; i < 50_0000; i++) {int[] arr = getArr();while (arr.length < 2){arr = getArr();}int lessIndex = getLessIndex(arr);if(lessIndex < 0){continue;}if (lessIndex==0|| (lessIndex == (arr.length-1) )|| (arr[lessIndex] < arr[lessIndex + 1] && arr[lessIndex] < arr[lessIndex - 1])) {System.out.println("\nok");}else{if(lessIndex - 1 >= 0){System.out.print("left: " + arr[lessIndex - 1]);}System.out.print(" less: " + arr[lessIndex]);if (lessIndex + 1 <= arr.length - 1) {System.out.print(" right: " + arr[lessIndex + 1]);}throw new RuntimeException("failed");}}}}
