咕咕了一周的算法专题今日起正式回归啦,今天总结一个看起来好像很简单,但实际上有点难的二分法
二分查找也常被称为二分法或者折半查找,每次查找时通过将待查找区间分成两部分并只取一部分继续查找,
将查找的复杂度大大减少。
给定一个非负整数,求它的开方,向下取整。
很简单,直接看代码吧
int my_sqrt(int num){
if(num==0)
return 0;
int l = 1, r = num, mid, sqrt;
while(l<=r){
int mid = l + (r - l) / 2;
sqrt = num / mid;
if(sqrt==mid){
return sqrt;
}
else if (mid > sqrt)
{
r = mid - 1;
}
else{
l = mid + 1;
}
}
}
给定一个增序的整数数组和一个值,查找该值第一次出现和最后一次出现的位置
要在一个增序的数组中寻找一个值第一次出现和最后一次出现的位置,可以转化为寻找这样两个值
1、第一个等于 target 的位置
2、第一个大于target 的位置
vector<int> findPosition(vector<int> nums, int target){
if( nums.empty() )
return {-1, -1};
int LIdx = 0;
int RIdx = 0;
int l = 0, r = nums.size() - 1;
int mid = 0;
while(l<=r){
mid = l + (r - l) / 2;
if(nums[mid]>=target)
r = mid - 1;
else{
l = mid + 1;
}
}
if(l>=nums.size()||nums[l]!=target)
return {-1, -1};
LIdx = l;
l = 0, r = nums.size() - 1;
while(l<=r){
mid = l + (r - l) / 2;
if(nums[mid]>target)
r = mid - 1;
else{
l = mid + 1;
}
}
RIdx = l - 1;
return {LIdx, RIdx};
}
在转动过的有序数组里寻找目标值
利用数组之前排好序的性质,通过比较nums[mid]和nums[right]的值的大小来判断左半部分还是右半部分有序
class Solution {
public:
int search(vector<int>& nums, int target) {
int n = (int)nums.size();
if (!n) {
return -1;
}
if (n == 1) {
return nums[0] == target ? 0 : -1;
}
int l = 0, r = n - 1;
while (l <= r) {
int mid = (l + r) / 2;
if (nums[mid] == target) return mid;
if (nums[0] <= nums[mid]) {
if (nums[0] <= target && target < nums[mid]) {
r = mid - 1;
} else {
l = mid + 1;
}
} else {
if (nums[mid] < target && target <= nums[n - 1]) {
l = mid + 1;
} else {
r = mid - 1;
}
}
}
return -1;
}
};