Binary search
Brush LC for the first time, make a little summary, a little excited
0. Basic
1. When calculating the mid index, you should
int mid = left + (right-left)/2;
instead of
int mid = (left+right)/2;
Can prevent left+right overflow (out of integer range)
2. If it is not bisection, it must be recursive like sorting
For simple lookup operations, loop can be solved
3. Key points: add one or subtract one for mid, and use < = or < = in while<
4. Basic framework:
int binarySearch(int[] nums, int target) { int left = 0, right = ...; while(...) { int mid = left + (right - left) / 2; if (nums[mid] == target) { ... } else if (nums[mid] < target) { left = ... } else if (nums[mid] > target) { right = ... } } return ...; }
1. Simple search 704
int left = 0 , right = numsSize-1 , mid; while (left <= right) { mid = left + (right - left)/2; if (nums[mid] == target) return mid; else if (nums[mid] < target) left = mid +1; else if (nums[mid] > target) right = mid -1; } return -1;
Keys: look in
right = numsSize-1 indicates that the search scope is [l,r] instead of [l,r]
Naturally, l == r is allowed, that is, the processing of an element
2. First wrong version 278
Find the boundary of left F and right T value
First attempt:
Find a T whose left adjacent element is F
Question:
- The first element has no left neighbor
- At this time, the left and right bounds [l,r) are used. If the last element is searched, the right bound is N+1, and the required int type cannot meet the right bound index of 2147483647 + 1
The second time:
Still take [l,r] until l==r-1 (i.e. l < R-1, l = = f, r = = t at the end)
Keys: bounds shrink
No exceptions considered: full T without F (- 1 Index undefined)
The fundamental problem is that the two elements [l,r] are retained, and the understanding and application of pointers are not flexible enough. L and r can be equal
Official answer:
int left = 1, right = n; while (left < right) { // Cycle until the left and right end points of the interval are the same int mid = left + (right - left) / 2; // Prevent overflow during calculation if (isBadVersion(mid)) { right = mid; // In interval [left, mid] (mid is T) } else { left = mid + 1; // In interval [mid+1, right) //(mid+1 is unknown, but right must be T) } } // At this time, there is left == right, and the interval is reduced to a point, which is the answer return left;
Take [l,r), discard mid and divide it into two intervals
Ensure that the right boundary must be T, and it is no problem to shrink the left boundary to l=r
While (left < right) is because l=r has been generated after the last operation. Just output it directly
3. Search insertion position 35
New problems when solving according to the method of question 1 [l, r]
- If there is only one array, there is no loop
- The right bound cannot be guaranteed to be greater than or equal to TARGET. It is possible that TARGET is larger than all numbers, that is, the value range of output is: [0, numsize]
solve:
//The while loop has ended if (nums[right] < target) return right +1; return right;
According to the method of question 2:
int left = 0 , right = numsSize-1 , mid; while (left <= right) { mid = left + (right - left)/2; if (nums[mid] == target) return mid; else if (nums[mid] < target) left = mid +1; else if (nums[mid] > target) right = mid -1; } return left; //Here - 1 can be changed to left
Why just change one place
If there is TG in the array, it is solved in the loop
If there is no TG in the array,
(the penultimate cycle has two elements, one is less than TG (marked as A), one is greater than TG (marked as B), and mid is A)
The last cycle has one element, A, mid is still A and less than TG
So left + +, that is, the position of B
In fact, because it is sorted, all elements before B are less than or equal to A, that is, less than TG
left is naturally the insertion position
4. Find the left boundary of a possible element
Similarly, question 2 [l, r)
int left = 0, right = numsSize; while (left < right) { int mid = left + (right - left)/2; if (nums[mid] == target) { right = mid; //When the same, don't rush back first, shrink to the left to see if there is repetition } else if (nums[mid] < target) { left = mid + 1; } else if (nums[mid] > target) { right = mid; } } return left;
5. Find the right boundary of a possible element
int left = 0, right = numsSize; while (left < right) { int mid = (left + right) / 2; if (nums[mid] == target) { left = mid + 1; //Shrink right } else if (nums[mid] < target) { left = mid + 1; } else if (nums[mid] > target) { right = mid; } } return left - 1; //The last loop also has left + +, that is, it must cross a bit
6. Harmonization
Use the variant of question 1 [l, r]
- To repeat the boundary of an element, shrink the boundary to the left and right under the condition of = =
- If the element does not exist, you need to judge whether the index is out of bounds (larger than all elements)
- Essence: the ends of the range are symmetrical at both ends, and one side is removed each time to realize contraction
Use the variant of the second question [l, r)
- To repeat the boundary of an element, shrink the boundary to the left and right under the condition of = =
- If the right boundary needs to be returned, - 1
- Essence: r) one side has a fixed property (e.g. > TG), so it can be removed and binary contraction can be carried out on one side
The essential difference between them is the division of interval in bisection
Even after the last operation, the results are slightly different, or the solutions to special situations are different
Refer to labuladong(LC)