Recognition = knowledge = two = points = law


The common dichotomy type is to conduct a dichotomy search on an ordered array. But is it really necessary to use dichotomy in solving all problems? Do not. Mainly can correctly construct the elimination logic on the left and right sides, and you can divide by two.

Common wording

mid = L + ((R - L) >> 1)

Because mid = (L + R) / 2, it may overflow when calculating L + R. So it becomes mid = L + (R-L) / 2. Because the subtraction of R-L will not overflow, it will not overflow even if it is divided, and after adding L, it must be smaller than R. If R does not overflow, it will definitely not overflow. Then / 2 can be converted to >> 1, because bit operations must be faster than division.

N * 2 + 1 = ((N << 1) | 1)

N * 2 + 1, can be written as ((N << 1) | 1), because a left shift is equivalent to * 2, at this time the rightmost bit must be 0, and then ORing with 1 is equivalent to +1 .

topic

Example 1: In an ordered array, find if a certain number exists?

pubilc 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);
		if (sortedArr[mid] == num) {
			return true;
		} else if (sortedArr[mid] > num) {
			R = mid-1;
		} else {
			L = mid+1;
		}	
	return sortedArr[mid] == num;
}

Example 2: In an ordered array, find> = the leftmost position of a number

pubilc 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) { // mid 比 value 大,说明在左边
			index = mid;
			R = mid - 1;
		} else {
			L = mid + 1;
		}
	}
	return index;
}

Example 3: In an ordered array, find the rightmost position of <= a number

pubilc 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;
}

Example 4: It is not necessary that any two numbers in the array are not equal, find the local minimum

First look at whether the 0 position is the local minimum (compared to the 1 position), if it is, then return, otherwise the trend is downward; then look at the N-1 position is local minimum (compared to the N-2 position), if it is Return, otherwise the trend is upward. [Note that the local minimum is not the global minimum] A curve that starts downward and ends with an upward trend must have a local minimum in the middle. So go directly to the mid position:
1) If the mid position is both smaller than the mid-1 position and smaller than the mid + 1 position, then return directly to the mid position value.
2) If mid is not the local minimum, then mid is either larger than the left, larger than the right, or larger than both sides, regardless of the situation. We might as well assume that mid is larger than mid-1, then it is indeed reproduced at the beginning, and I do n’t need the right side of mid, directly on the left side.
Note that you don't need to search around, just make sure there is a local minimum on one side.

public static int getLessIndex(int[] arr) {
	if (arr == null || arr.length == 0) {
		return -1;
	}
	if (arr[0] < arr[1])
		return 0;
	if (arr[arr.length-1] < arr[arr.length-2]) 
		return arr.length-1;
	
	int L = 1;
	int R = arr.length-2;
	int mid = 0;
	while (L < R) {
		mid = L + ((R - L) >> 1);
		if (arr[mid] > arr[mid - 1]) {
			R = mid - 1;
		} else if (arr[mid] > arr[mid + 1]) {
			L = mid + 1;
		} else { // 表示既比左边小又比右边小
			return mid;
		}
	}
	return left;
}
Published 40 original articles · Likes0 · Visits 384

Guess you like

Origin blog.csdn.net/weixin_43780400/article/details/105633327