一、二分法的详解与扩展
1.二分法详解
@1.在有序的数组中的查找方法,二分查找。基本思想是看中点是不是满足条件,不满足修正端点,再次看中点是否满足题意。
一般思路是:初始化端点和中点
然后while(L<R)
赋值中点
然后是否满足条件 返回
然后情况一,正左端点=中值
情况二,右端点=中值。
(可能出现第三种情况)
2.在一个有序数组中,找某个数是否存在
只要找到就可以
public static boolean Exist( int [] arr,int num) {
if(arr == null || arr.length == 0) {
return false;
}
int L = 0;
int R = arr.length - 1;
int mid = 0;
while(L<R) {
mid = L + ((R-L) >> 1);
if(arr[mid] == num) {
return true;
} else if(arr[mid]>num) {
R = mid - 1 ;
}else {
L= mid + 1;
}
}
return arr[L] == num;
}
3.在一个有序数组中,找>=某个数最左侧的位置
注意一定要分到最后
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.局部最小值问题
局部最小值问题使用二分法,就证明着,二分法,有时并不需要严格有序,只要能保证二分后,必有问题的一个解就行
局部最小,也就是局部极小值,有点像变化率:
a[i]<a[i-1]且a[i]<a[i+1]有点像极小值
要求:
用时间复杂度BIG O(N)的方法,找出一个数组中的一个局部最小值。且已知相邻两个数组的值不一样
思路:
先判断两个端点:
a[0]<a[1]
a[n-1]<a[n-2]
满足即找到了
然后再踏入二分
public int findPeak(int[] nums) {
int N = nums.length;
if (N == 1) {
return 0;
}
if (nums[0] < nums[1]) {
return 0;
}
if (nums[N - 1] < nums[N - 2]) {
return N - 1;
}
int low = 0, high = N - 1;
while (low < high) {
int mid = (low + high) / 2;
if (nums[mid - 1] > nums[mid] && nums[mid] < nums[mid + 1]) {
return mid;
} else if (nums[mid - 1] < nums[mid] && nums[mid] < nums[mid + 1]) {
high = mid;
} else if (nums[mid - 1] > nums[mid] && nums[mid] > nums[mid + 1]) {
low = mid;
}
}
return -1;
}