二分法相关题
二分法模板
while (l < r) {
long mid = l + r + 1 >> 1;
if (check(mid)) {
l = mid;
} else {
r = mid - 1;
}
}
或者·
long l = 0, r = 1000009;
while (l < r) {
long mid = l + r >> 1;
if (check(mid)) {
r = mid;
} else {
l = mid + 1;
}
}
在排序数组中查找数字
法1:直接经过两次「二分」找到左右边界,计算总长度即是 targettarget 的数量
class Solution {
public int search(int[] nums, int target) {
int n = nums.length;
if (n == 0) return 0;
int left = 0;
int right = n - 1;
int l = -1;
int r = -1;
//左边界
while (left < right) {
int mid = left + ((right - left) >> 1);
if (nums[mid] >= target) {
right = mid;
} else {
left = mid + 1;
}
}
if (nums[right] != target) return 0;
l = right;
//右边界
left = 0;
right = n - 1;
while (left < right) {
int mid2 = left + ((right - left + 1) >> 1);
if (nums[mid2] <= target) {
left = mid2;
} else {
right = mid2 - 1;
}
}
if (nums[right] != target) return 0;
r = right;
return r - l + 1;
}
}
法2:找到目标值 target 「首次」出现或者「最后」出现的下标,然后「往后」或者「往前」进行数量统计。
class Solution {
public int search(int[] nums, int target) {
int n=nums.length;
if(n==0) return 0;
int left=0;
int right=n-1;
//右边界
while(left<right){
int mid=left+((right-left+1)>>1);
if(nums[mid]<=target){
left=mid;
}
else{
right=mid-1;
}
}
int ans=0;
while(right>=0&&nums[right]==target&&right-->=0){
ans++;
}
return ans;
}
}
往前扫描
while(right>=0&&nums[right]==target&&right-->=0){
}
往后扫描
while(left<n&&nums[left]==target&&left++>=0){
}
倍增模板
long mul(long a, long k) {
long ans = 0;
while (k > 0) {
if ((k & 1) == 1)
ans += a;
k >>= 1;
a += a;
}
return ans;
}