认识二分法

原理:

从一个有序数组里面,找中间位置的数(不用时间),判断中间的数和目标数字的大小,目标数字比中间的小,则需要找的范围就在中间位置的左边,直到最后一个数,如果最后一个数都不等于那么不存在这个数。

这是O(log2N)的算法

因为一共砍了log2N次(找中间值的次数),比大小的时间是O(1)。

二分法解决的问题:

  1. 在一个有序数组中,找某个数存不存在

  2. 在一个有序数组中,找大于某个数的最左位置

    比如【1】【2】【3】【3】【3】

    找大于等于三的最左位置就是下标为2的位置

  3. 在一个有序数组中,找到小于等于某个数的最右位置

  4. 局部最小值问题

二分代码:

1.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public static boolean exist(int[] sortedArr, int num){
if(sortedArr == null || sortedArr.length == 0){
return false;
}
int L = 0;
int R = sortedArr.length - 1;
int mid = 0;
while(L < R){
mid = L +((R - L) >> 1);// mid = (L + R) / 2
if(sortedArr[mid] == num){
return true;
} else if (sortedArr[mid] > num){
R = mid - 1;
} else {
L = mid + 1;
}
}
return sortedArr[L] == num;
}

2.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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;
R = mid -1;
} else {
L = mid + 1;
}
}
return index;
}

4.在一个无序数组中,任意相邻的数不相等。

什么叫局部最小,就是比如在0位置上的数,比1位置上的数小,那么0位置的数就是局部最小,如果N-1的数比N-2位置的数小那么N=1的数就是局部最小,如果任意 i 位置的数那么要比它左右两边都小那么 i 就是局部最小,一个数组中有很多局部最小只要返回一个就可以了。

原理:

先单独看0位置的数是不是单独最小,如果是直接返回0位置的数,如果不是那么说明0~1位置是一个向下的位置,

再单独看N-1和N-2位置,如果N-1是局部最小如果是直接返回,如果不是那么说明N-2~N-1是上升的,那么在下降和上升中肯定有局部最小的数。

再看中点位置,如果中点位置比左边和右边小那么直接返回中点,如果不成立那么从左边找或者右边小都行,因为一边下降一边上扬,必存在一个点是局部最小。

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
public static int getLessIndex(int[] arr){
if(arr == null || arr.length == 0){
return -1;
}
if(arr.length == 1 || arr[0] <arr[1]){
return 0;
}
if(arr[arr.length - 1] < arr[arr.length - 2]) {
return arr.length - 1;
}
int left = 1;
int right = arr.length - 2;
int mid = 0;
while(left < right){
mid = (left + right) >> 1;
if(arr[mid] > arr[mid -1]){
right = mid -1;
} else if (arr[mid] > arr[mid +1]) {
left = mid + 1;
} else {
return mid;
}
}
return left;
}