1.在一个有序的数组中,查找某一个数是否存在
2.在一个有序的数组中,查找>=2的最左侧位置
3.找到一个局部最小值

在一个有序的数组中,查找某一个数是否存在

找num是否存在 先找一个中间位置 middleIndex middleIndex==num 存在 middleIndex>num 右边一定没有num,可能在左边存在num middleIndex<num 左边一定没有num,可能在右边存在num 如此往复,指导剩下最后一个数没办法再二分

  1. package com.ss.sort;
  2. import java.util.Arrays;
  3. import java.util.Random;
  4. /**
  5. * <p>
  6. * 在一个有序的数组中,查找某一个数是否存在
  7. * </P>
  8. *
  9. * @author: zhangss
  10. * @since: 2021-01-05
  11. **/
  12. public class BinarySearchExist {
  13. public static boolean exist(int[] arr, int num){
  14. if(null == arr || arr.length < 1){
  15. return false;
  16. }
  17. if(arr.length == 1 && arr[0] == num){
  18. return true;
  19. }
  20. int l = 0, r = arr.length - 1, mid;
  21. while (l < r) {
  22. mid = l + (r - l) / 2;
  23. if(arr[mid] == num){
  24. return true;
  25. }else if(arr[mid] > num){
  26. r = mid - 1;
  27. }else{
  28. l = mid + 1;
  29. }
  30. }
  31. return arr[l] == num;
  32. }
  33. public static boolean comparator(int[] arr, int num){
  34. return exist(arr, num) == Arrays.binarySearch(arr, num) >= 0;
  35. }
  36. /**
  37. * 产生有序数组
  38. * @return
  39. */
  40. public static int[] getSortedArr(){
  41. Random random = new Random();
  42. // 若电脑性能有限,生成的数组可以降低长度
  43. int length = random.nextInt(10);
  44. int[] arr = new int[length];
  45. for(int i = 0; i < length; i++){
  46. arr[i] = random.nextInt(100);
  47. }
  48. Arrays.sort(arr);
  49. return arr;
  50. }
  51. public static void main(String[] args) {
  52. for (int i = 0; i < 50; i++) {
  53. Random random = new Random();
  54. int[] arr = getSortedArr();
  55. int num = random.nextInt(100);
  56. if(!comparator(arr, num)){
  57. System.out.println("第" + (i + 1) + "次");
  58. System.out.println(Arrays.toString(arr));
  59. System.out.println("num: " + num);
  60. System.out.println("失败\n");
  61. }
  62. }
  63. }
  64. }

在一个有序的数组中,查找>=2的最左位置

找num的最左位置 找到中间位置mid, 初始化最左侧位置leftIndex = -1 mid = 2 leftIndex = mid 左边可能有=2的最左位置, 继续找左边 mid > 2 leftIndex = mid 左边可能有=2的最左位置, 继续找左边 mid < 2 右边可能有最左侧位置,继续找右边

  1. package com.ss.sort;
  2. import java.util.Arrays;
  3. import java.util.Random;
  4. /**
  5. * <p>
  6. * 在一个有序的数组中,查找>=2的最左位置
  7. * </P>
  8. *
  9. * @author: zhangss
  10. * @since: 2021-01-05
  11. **/
  12. public class BinarySearchNearLeft {
  13. public static int nearLeft(int[] arr, int num){
  14. if(null == arr || arr.length < 1){
  15. return -1;
  16. }
  17. if(arr.length == 1 && arr[0] >= num){
  18. return 0;
  19. }
  20. int l = 0, r = arr.length - 1, mid = 0, leftIndex = -1;
  21. while (l <= r){
  22. mid = l + (r - l) / 2;
  23. if(arr[mid] >= num){
  24. leftIndex = mid;
  25. r = mid - 1;
  26. }else{
  27. l = mid + 1;
  28. }
  29. }
  30. return leftIndex;
  31. }
  32. public static int comparator(int[] arr, int num) {
  33. int leftIndex = -1;
  34. for (int i = 0; i < arr.length; i++) {
  35. if (arr[i] >= num) {
  36. leftIndex = i;
  37. break;
  38. }
  39. }
  40. return leftIndex;
  41. }
  42. /**
  43. * 产生有序数组
  44. * @return
  45. */
  46. public static int[] getSortedArr(){
  47. Random random = new Random();
  48. // 若电脑性能有限,生成的数组可以降低长度
  49. int length = random.nextInt(5);
  50. length = length < 2 ? 2 : length;
  51. int[] arr = new int[length];
  52. for(int i = 0; i < length; i++){
  53. arr[i] = random.nextInt(10);
  54. }
  55. Arrays.sort(arr);
  56. return arr;
  57. }
  58. public static void main(String[] args) {
  59. Random random = new Random();
  60. for (int i = 0; i < 50000; i++) {
  61. int[] sortedArr = getSortedArr();
  62. int numIdx = Math.abs(random.nextInt(sortedArr.length - 1));
  63. int i1 = nearLeft(sortedArr, sortedArr[numIdx]);
  64. int i2 = comparator(sortedArr, sortedArr[numIdx]);
  65. if(i1 != i2){
  66. System.out.println(Arrays.toString(sortedArr));
  67. System.out.println(sortedArr[numIdx]);
  68. System.out.println("failed");
  69. }
  70. }
  71. }
  72. }

找到一个局部最小值

局部最小值: 最左边的值小,比右边的值大,就是局部最小值 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] 说明右边必有局部最小 找到一个就返回

  1. package com.ss.sort;
  2. import java.util.Arrays;
  3. import java.util.Random;
  4. /**
  5. * <p>
  6. * 找到一个局部最小值
  7. * </P>
  8. *
  9. * @author: zhangss
  10. * @since: 2021-01-05
  11. **/
  12. public class BinarySearchAwesome {
  13. /**
  14. * 找到一个局部最小值的下标
  15. * @param arr
  16. * @return
  17. */
  18. public static int getLessIndex(int[] arr){
  19. if(null == arr || arr.length < 1){
  20. return -1; // not exist
  21. }
  22. if(arr.length > 1 && arr[0] < arr[1]){
  23. return 0;
  24. }
  25. if (arr.length > 1 && arr[arr.length - 1] < arr[arr.length - 2]) {
  26. return arr.length - 1;
  27. }
  28. // 第一个和最后一个都不是局部最小,所以第一个和最后一个都不检查了
  29. int l = 1, r = arr.length - 2, midIdx = -1;
  30. while (l <= r){
  31. midIdx = l + (r - l) / 2;
  32. if (arr[midIdx] < arr[midIdx + 1]) {
  33. r = midIdx - 1;
  34. } else if (arr[midIdx] > arr[midIdx + 1]) {
  35. l = midIdx + 1;
  36. } else {
  37. return midIdx;
  38. }
  39. }
  40. return l;
  41. }
  42. /**
  43. * 生成测试数据
  44. * 无序,不重复
  45. * @return
  46. */
  47. public static int[] getArr(){
  48. Random random = new Random();
  49. int[] arr = {};
  50. for (int num = 0; num < random.nextInt(100); num++){
  51. int length = random.nextInt(10);
  52. length = length > 1 ? length : 2;
  53. int[] tempArr = new int[length];
  54. for (int i = 0; i < tempArr.length; i++) {
  55. tempArr[i] = random.nextInt(100);
  56. }
  57. tempArr = Arrays.stream(tempArr).distinct().sorted().toArray();
  58. if(random.nextInt(1000)%2 == 0){
  59. tempArr = reverse(tempArr);
  60. }
  61. arr = Arrays.copyOf(arr, arr.length + tempArr.length);
  62. for(int i = arr.length - tempArr.length, j = 0; i < arr.length; i++, j++){
  63. arr[i] = tempArr[j];
  64. }
  65. }
  66. arr = Arrays.stream(arr).distinct().toArray();
  67. return arr;
  68. }
  69. /**
  70. * 反转数组
  71. * @param arr
  72. * @return
  73. */
  74. public static int[] reverse(int[] arr){
  75. int[] newInt = new int[arr.length];
  76. for (int i = newInt.length - 1, j = 0 ; i > -1; i--, j++) {
  77. newInt[j] = arr[i];
  78. }
  79. return newInt;
  80. }
  81. /**
  82. * 测试50w次,确认方法没问题
  83. * @param args
  84. */
  85. public static void main(String[] args) {
  86. for (int i = 0; i < 50_0000; i++) {
  87. int[] arr = getArr();
  88. while (arr.length < 2){
  89. arr = getArr();
  90. }
  91. int lessIndex = getLessIndex(arr);
  92. if(lessIndex < 0){
  93. continue;
  94. }
  95. if (lessIndex==0
  96. || (lessIndex == (arr.length-1) )
  97. || (arr[lessIndex] < arr[lessIndex + 1] && arr[lessIndex] < arr[lessIndex - 1])) {
  98. System.out.println("\nok");
  99. }else{
  100. if(lessIndex - 1 >= 0){
  101. System.out.print("left: " + arr[lessIndex - 1]);
  102. }
  103. System.out.print(" less: " + arr[lessIndex]);
  104. if (lessIndex + 1 <= arr.length - 1) {
  105. System.out.print(" right: " + arr[lessIndex + 1]);
  106. }
  107. throw new RuntimeException("failed");
  108. }
  109. }
  110. }
  111. }