二分法
中心思想:
对于有一定顺序的数组找里面的特殊值,将数组分为2部分,这个特殊值只能在其中一部分里。数组的两部分分别是low-mid和mid-high。如果判断出特殊值在low-mid中,则high=mid,如果判断出特殊值在mid-high中,则low=mid+1。其中mid=low+(high-low)/2。然后继续重新判断。
重点:
当 mid 的计算公式为 low + (high-low) / 2时,记住一定是low=mid+1和high=mid。也就是说+1是放在low那一侧的
while里是hi>lo,这样退出循环时就是high=low
对于特殊例子,需要单独计算
基础代码:
class Solution {
public:
int Number(vector<int>& nums) {
int lo = 0;
int hi = nums.size() - 1;
while (hi>lo) {
int mid = lo + (hi - lo) / 2;
if (mid == nums[mid]) //根据特殊值的特点设置条件
lo = mid + 1;
else
hi = mid;
}
return nums[lo];
}
};
题1:
答案:
class Solution {
public:
int searchInsert(vector<int>& nums, int target) {
int lo = 0;
int hi = nums.size() - 1;
if (target > nums[hi]) //特殊情况
return nums.size();
if (nums.size() == 0) //特殊情况
return 0;
while (lo < hi) {
int mid = lo + (hi - lo) / 2;
if (nums[mid] < target)
lo = mid + 1;
else
hi=mid;
}
return lo ;
}
};
题2:
、
答案:
class Solution {
public:
vector<int> searchRange(vector<int>& nums, int target) {
int lo = 0;
int hi = nums.size()-1;
if (hi < 0) return{ -1,-1 }; //特殊情况
//找左边界,定位在第一个target上
while (lo < hi) {
int mid = lo + (hi - lo) / 2;
if (target > nums[mid])
lo = mid + 1;
else
hi = mid;
}
int leftdex = lo;
lo = 0;
hi = nums.size() - 1;
//找右边界,定义在最后一个target的后边的一个元素
while (lo < hi) {
int mid = lo + (hi - lo) / 2;
if (target >= nums[mid])
lo = mid+1;
else
hi = mid;
}
int rightdex = lo-1;
if (nums[leftdex] != target) //特殊情况
return{ -1,-1 };
int part = nums.size() - 1;
if ( nums[nums.size() - 1] == target) return{ leftdex,part }; //特殊情况
return{ leftdex,rightdex};
}
};
题3:
答案:
class Solution {
public:
int minArray(vector<int>& numbers) {
int lo = 0;
int hi = numbers.size() - 1;
while (lo < hi) {
int mid = lo + (hi - lo) / 2;
if (numbers[mid] > numbers[hi])
lo = mid + 1;
else if (numbers[mid] > numbers[hi])
hi = mid;
else
hi--;
}
return numbers[lo];
}
};
题4:
答案:
class Solution {
public:
int missingNumber(vector<int>& nums) {
int lo = 0;
int hi = nums.size() - 1;
if (nums[0] == 1) return 0;
if (nums[nums.size() - 1] == nums.size() - 1) return nums.size();
while (hi>lo) {
int mid = lo + (hi - lo) / 2;
if (mid == nums[mid])
lo = mid + 1;
else
hi = mid;
}
return nums[lo] - 1;
}
};