有序数组中找到一个数num
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
|
public class Getnum01_in_sortedarray { public static boolean find(int[] arr,int num) { if (arr == null || arr.length == 0) { return false; } int L = 0; int R = arr.length - 1 ; while (L <= R) { int mid = (L + R)/2; if (arr[mid] < num) { L = mid + 1; } else if (arr[mid] > num ) { R = mid - 1; } else { return true; } } return false; } }
|
升序有序数组中找到大于等于num的最左位置
位置从0开始 , [1,2,2,2,3,4,5,5,6,7]
num = 2 ,>=num最左的位置是1 。如果num=4 ,>=num最左的位置是5
要点: 二分不会在找到某个数就停止,必须全部二分完毕才会停止。 记录>=num的位置,并一直更新它。
能处理找不到该数的极端情况。返回-1
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| public class Getnum02_mostLeftNoLess_in_sortedarray {
public static int mostLeftNoLessNumIndex(int[] arr,int num) { if (arr == null || arr.length == 0) { return -1; } int L = 0; int R = arr.length -1; int answer = -1; while (L <=R) { int mid = (L + R) /2; if (arr[mid] >= num) { answer = mid; R = mid - 1; } else { L = mid + 1; } } return answer; } }
|
升序有序数组中找到小于等于num的最右位置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73
| import java.util.Arrays;
public class Getnum03_mostRightNoMore_in_sortedarray {
public static int nearestIndex(int[] arr, int value) { int L = 0; int R = arr.length - 1; int index = -1; while (L <= R) { int mid = L + ((R - L) >> 1); if (arr[mid] <= value) { index = mid; L = mid + 1; } else { R = mid - 1; } } return index; }
public static int test(int[] arr, int value) { for (int i = arr.length - 1; i >= 0; i--) { if (arr[i] <= value) { return i; } } return -1; }
public static int[] generateRandomArray(int maxSize, int maxValue) { int[] arr = new int[(int) ((maxSize + 1) * Math.random())]; for (int i = 0; i < arr.length; i++) { arr[i] = (int) ((maxValue + 1) * Math.random()) - (int) (maxValue * Math.random()); } return arr; }
public static void printArray(int[] arr) { if (arr == null) { return; } for (int i = 0; i < arr.length; i++) { System.out.print(arr[i] + " "); } System.out.println(); }
public static void main(String[] args) { int testTime = 500000; int maxSize = 10; int maxValue = 100; boolean succeed = true; for (int i = 0; i < testTime; i++) { int[] arr = generateRandomArray(maxSize, maxValue); Arrays.sort(arr); int value = (int) ((maxValue + 1) * Math.random()) - (int) (maxValue * Math.random()); if (test(arr, value) != nearestIndex(arr, value)) { printArray(arr); System.out.println(value); System.out.println(test(arr, value)); System.out.println(nearestIndex(arr, value)); succeed = false; break; } } System.out.println(succeed ? "Nice!" : "Fucking fucked!"); }
}
|
局部最小值
条件:有一个数组,无序, 任意两个相邻的数不想等。
什么是局部最小,有三种情况:
- [0] < [1] ,则 0位置局部最小 有,则返回0位置
- [n-2] > [n-1] ,则n-1位置局部最小。 有,则返回n-1位置
- 左>[i]<右 , 则i位置局部最小。 如果1,2都没有,则3必有局部最小。
期望:返回一个局部最小的数。
二分后,mid 检查mid是否满足,满足则直接返回。
如果mid不满足,看mid左右两侧哪个比mid小,说明这一侧必存在局部最小,砍掉另一侧。 -继续二分。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86
| public class Getnum04_in_near_sortedarray {
public static int oneMinIndex(int[] arr) { if (arr == null || arr.length == 0) { return -1; } int N = arr.length; if (N == 1) { return 0; } if (arr[0] < arr[1]) { return 0; } if (arr[N - 1] < arr[N - 2]) { return N - 1; } int L = 0; int R = N - 1; while (L < R - 1) { int mid = (L + R) / 2; if (arr[mid] < arr[mid - 1] && arr[mid] < arr[mid + 1]) { return mid; } else { if (arr[mid] > arr[mid - 1]) { R = mid - 1; } else { L = mid + 1; } } } return arr[L] < arr[R] ? L : R; }
public static int[] randomArray(int maxLen, int maxValue) { int len = (int) (Math.random() * maxLen); int[] arr = new int[len]; if (len > 0) { arr[0] = (int) (Math.random() * maxValue); for (int i = 1; i < len; i++) { do { arr[i] = (int) (Math.random() * maxValue); } while (arr[i] == arr[i - 1]); } } return arr; }
public static boolean check(int[] arr, int minIndex) { if (arr.length == 0) { return minIndex == -1; } int left = minIndex - 1; int right = minIndex + 1; boolean leftBigger = left >= 0 ? arr[left] > arr[minIndex] : true; boolean rightBigger = right < arr.length ? arr[right] > arr[minIndex] : true; return leftBigger && rightBigger; }
public static void printArray(int[] arr) { for (int num : arr) { System.out.print(num + " "); } System.out.println(); }
public static void main(String[] args) { int maxLen = 100; int maxValue = 200; int testTime = 1000000; System.out.println("测试开始"); for (int i = 0; i < testTime; i++) { int[] arr = randomArray(maxLen, maxValue); int ans = oneMinIndex(arr); if (!check(arr, ans)) { printArray(arr); System.out.println(ans); break; } } System.out.println("测试结束"); } }
|