Binary Search is generally composed of 3 main sections:
Pre-processing - Sort if collection is unsorted.
Binary Search - Using a loop or recursion to divide search space in half after each comparison.
Post-processing - Determine viable candidates in the remaining space.
参考:https://leetcode.com/explore/learn/card/binary-search/125/template-i/950
int binarySearch(vector& nums, int target){
if(nums.size() == 0)
return -1;
int left = 0, right = nums.size() - 1;
while(left <= right){
// Prevent (left + right) overflow
int mid = left + (right - left) / 2;
if(nums[mid] == target){ return mid; }
else if(nums[mid] < target) { left = mid + 1; }
else { right = mid - 1; }
}
// End Condition: left > right
return -1;
}
模板一是二分法搜索的最基本的形式,该模板用于搜索一个可以通过访问数组中的单个索引来确定的元素。搜索结束后不需要进行后处理。
Template #1 is the most basic and elementary form of Binary Search. It is the standard Binary Search Template that most high schools or universities use when they first teach students computer science. Template #1 is used to search for an element or condition which can be determined by accessing a single index in the array.
Search Condition can be determined without comparing to the element's neighbors (or use specific elements around it)
No post-processing required because at each step, you are checking to see if the element has been found. If you reach the end, then you know the element is not found
Distinguishing Syntax:
left = 0, right = length-1
left > right
right = mid-1
left = mid+1
应用1:
Sqrt(x)Implement int sqrt(int x)
.
Compute and return the square root of x, where x is guaranteed to be a non-negative integer.
Since the return type is an integer, the decimal digits are truncated and only the integer part of the result is returned.
Input: 8
Output: 2
Explanation: The square root of 8 is 2.82842..., and since
the decimal part is truncated, 2 is returned.
在不使用牛顿法的情况下,我们使用二分法如下:
class Solution {
public:
int mySqrt(int x) {
if(x == 0)
return 0;
int left = 1, right = INT_MAX;
while(left<=right){
int mid = left + (right - left)/2;
//"mid > x/mid" can prevent overflow
if(mid > x/mid){
right = mid - 1;
}else{
if(mid+1 > x/(mid+1))
return mid;
left = mid + 1;
}
}
}
};
1.If mid * mid > x, mid > x/mid
is true, because x/mid
is not greater than the real value of x/mid.
2.If mid * mid = x, because x/mid
is equal to mid
, mid > x/mid
is false.
3.If mid * mid < x, because the integer part of x/mid is greater or equal to mid
, mid <= x/mid
is true. Hence mid > x/mid
is false.
Therefore, if mid>x/mid
is true, mid
is really greater than x/mid. Further, mid is greater than sqrt(x)
.
When mid > x/mid
is false, and mid+1 > x/mid+1
is true, we find the answer, because mid<=sqrt(x) && mid+1>sqrt(x)
.
https://blog.csdn.net/qq_25800311/article/details/82720942
int binarySearch(vector& nums, int target){
if(nums.size() == 0)
return -1;
int left = 0, right = nums.size();
while(left < right){
// Prevent (left + right) overflow
int mid = left + (right - left) / 2;
if(nums[mid] == target){ return mid; }
else if(nums[mid] < target) { left = mid + 1; }
else { right = mid; }
}
// Post-processing:
// End Condition: left == right
if(left != nums.size() && nums[left] == target) return left;
return -1;
}
Template #2 is an advanced form of Binary Search. It is used to search for an element or condition which requires accessing the current index and its immediate right neighbor's index in the array.
模板二是二分法搜索的高级形式,当在数组中搜索一个元素时需要访问当前索引元素及其右邻居索引的元素,可采用该模板。
关键属性:
区分语法:
left = 0, right = length
left == right
right = mid
left = mid+1
Post-processing: need
Suppose an array sorted in ascending order is rotated at some pivot unknown to you beforehand.
(i.e., [0,1,2,4,5,6,7]
might become [4,5,6,7,0,1,2]
).
Find the minimum element.
You may assume no duplicate exists in the array.
Example 1:
Input: [3,4,5,1,2]
Output: 1
Example 2:
Input: [4,5,6,7,0,1,2]
Output: 0
思路:
Looking at subarray with index [start,end]. We can find out that if the first member is less than the last member, there's no rotation in the array. So we could directly return the first element in this subarray.
If the first element is larger than the last one, then we compute the element in the middle, and compare it with the first element. If value of the element in the middle is larger than the first element, we know the rotation is at the second half of this array. Else, it is in the first half in the array.
int findMin(vector &num) {
int start=0,end=num.size()-1;
while (start=num[start]) {
start = mid+1;
} else {
end = mid;
}
}
//这里没有进行后处理的原因是最小值一定存在
return num[start];
}
int binarySearch(vector& nums, int target){
if (nums.size() == 0)
return -1;
int left = 0, right = nums.size() - 1;
while (left + 1 < right){
// Prevent (left + right) overflow
int mid = left + (right - left) / 2;
if (nums[mid] == target) {
return mid;
} else if (nums[mid] < target) {
left = mid;
} else {
right = mid;
}
}
// Post-processing:
// End Condition: left + 1 == right
if(nums[left] == target) return left;
if(nums[right] == target) return right;
return -1;
}
Template #3 is another unique form of Binary Search. It is used to search for an element or condition which requires accessing the current index and its immediate left and right neighbor's index in the array.
关键属性:
区分语法:
left = 0, right = length-1
left + 1 == right
right = mid
left = mid
Post-processing: need
应用实例:
https://blog.csdn.net/qq_25800311/article/details/82733711
https://leetcode.com/explore/learn/card/binary-search/135/template-iii/944/discuss/14699/Clean-iterative-solution-with-two-binary-searches-(with-explanation)
99% of binary search problems that you see online will fall into 1 of these 3 templates. Some problems can be implemented using multiple templates, but as you practice more, you will notice that some templates are more suited for certain problems than others.
Note: The templates and their differences have been colored coded below.
These 3 templates differ by their:
Template 1 and 3 are the most commonly used and almost all binary search problems can be easily implemented in one of them. Template 2 is a bit more advanced and used for certain types of problems.
Each of these 3 provided templates provide a specific use case:
Template #1 (left <= right)
:
Template #2 (left < right)
:
Template #3 (left + 1 < right):
Time and Space Complexity:
Runtime: O(log n)
-- Logorithmic Time
Because Binary Search operates by applying a condition to the value in the middle of our search space and thus cutting the search space in half, in the worse case, we will have to make O(log n) comparisons, where n is the number of elements in our collection.
Why
log n
?
- Binary search is performed by dividing the existing array in half.
- So every time you a call the subroutine ( or complete one iteration ) the size reduced to half of the existing part.
- First
N
becomeN/2
, then it becomeN/4
and go on till it find the element or size become 1.- The maximum no of iterations is
log N
(base 2).
Space: O(1)
-- Constant Space
Although, Binary Search does require keeping track of 3 indicies, the iterative solution does not typically require any other additional space and can be applied directly on the collection itself, therefore warrants O(1)
or constant space.