摘自Leetcode基础教程
附加:YZT去年刷题记录
1.二分查找
核心思想:二分查找维护查找空间的左、右和中间指示符,并比较查找目标或将查找条件应用于集合的中间值;如果条件不满足或值不相等,则清除目标不可能存在的那一半,并在剩下的一半上继续查找,直到成功为止。如果查以空的一半结束,则无法满足条件,并且无法找到目标。
其c++写法的标准模板如下:
int binarySearch(vector<int>& 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;
}
其中循环终止条件为左指针超过右指针
,或者当找到目标时;否则按情况调整左右指针。
值得参考:fucking-algorithm
模板2:
int binarySearch(vector<int>& 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;
}
二分法的三个模板如下:
2.例题
2.1 x的平方根
int mySqrt(int x) {
int l = 0, r = x, ans = -1;
while (l <= r) {
int mid = l + (r - l) / 2;
if ((long long)mid * mid <= x) {
ans = mid;
l = mid + 1;
}
else {
r = mid - 1;
}
}
return ans;
}
2.2 搜索旋转排序数组
解题思路: 这道题与搜索旋转数字的位置不同。判断中间mid与右侧的关系:
1)如果mid的值大于最右侧,则mid处于左侧的递增序列,表明mid往左均为递增序列;
2)否则,mid处于右侧的递增序列,表明mid往右均为递增序列。
根据上述递增序列的特点,判断target是否在递增序列中,进行区间的取舍。