模板1的条件为mid < target,因此l右移并且l一定不是mid,l = mid + 1,但是mid >= target时r左移有可能为正确答案
所以r = mid
while(l < r){
mid = l + r >> 1;
if(check(mid)) l = mid + 1;
else r = mid;
}
return l;
模板2的条件为mid <= target,因此l右移并且l可能是mid,l = mid,但是mid > target时r左移不可能为正确答案
所以r = mid - 1
while(l < r){
mid = l + r + 1 >> 1;
if(check(mid)) l = mid;
else r = mid - 1;
}
return l;
check函数设置为mid * mid <= x,选择模板2:
class Solution {
public:
int mySqrt(int x) {
int l = 0, r = x, mid;
while(l < r) {
mid = (long long)r + l + 1 >> 1;
if(mid <= x / mid) l = mid;
else r = mid - 1;
}
return l;
}
};
class Solution {
public:
int searchInsert(vector<int>& nums, int target) {
int l = 0, r = nums.size() - 1, mid;
while(l < r) {
mid = l + r + 1 >> 1;
if(nums[mid] == target) return mid;
else if(nums[mid] < target) l = mid;
else r = mid - 1;
}
return nums[l] >= target ? l : l + 1;
}
};
easy method
class Solution {
public:
vector<int> searchRange(vector<int>& nums, int target) {
int l = 0, r = nums.size() - 1, mid;
vector<int> res = {-1, -1};
if(r < 0) return res;
while(l < r) {
mid = l + r >> 1;
if(nums[mid] < target) l = mid + 1;
else r = mid;
}
if(nums[l] != target) return res;
res[0] = l;
l = 0, r = nums.size() - 1;
while(l < r) {
mid = l + r + 1 >> 1;
if(nums[mid] <= target) l = mid;
else r = mid - 1;
}
res[1] = l;
return res;
}
};
faster version
class Solution {
public:
vector<int> searchRange(vector<int>& nums, int target) {
int left = 0, right = nums.size() - 1, mid;
vector<int> ret = {-1, -1};
if(nums.size() == 0) return ret;
while(left <= right) {
mid = (left + right) / 2;
if(nums[mid] == target) {
int i = mid;
while(i >= 0 && nums[i] == target) ret[0] = i--;
i = mid;
while(i < nums.size() && nums[i] == target) ret[1] = i++;
break;
}
else if(nums[mid] > target) right = mid - 1;
else left = mid + 1;
}
return ret;
}
};
class Solution {
public:
bool searchMatrix(vector<vector<int>>& matrix, int target) {
int l = 0, r = matrix.size() - 1, mid, n = matrix[0].size() - 1;
if(target < matrix[0][0] || target > matrix[r][n]) return false;
if(target == matrix[0][0] || target == matrix[r][n]) return true;
while(l < r) {
mid = l + r + 1 >> 1;
if(matrix[mid][0] <= target) l = mid;
else r = mid - 1;
}
int loc = l;
l = 0, r = n;
while(l < r) {
mid = l + r + 1 >> 1;
if(matrix[loc][mid] <= target) l = mid;
else r = mid - 1;
}
return matrix[loc][l] == target ? true : false;
}
};
class Solution {
public:
int findMin(vector<int>& nums) {
int l = 0, r = nums.size() - 1, mid;
while(l < r) {
mid = l + r >> 1;
if(nums[mid] >= nums[l] && nums[mid] > nums[r]) {
l = mid + 1;
} else if(nums[mid] >= nums[l] && nums[mid] < nums[r]) {
r = mid;
} else if(nums[mid] <= nums[l] && nums[mid] < nums[r]) {
r = mid;
}
}
return nums[l];
}
};
做得我心脏疼
class Solution {
public:
int search(vector<int>& nums, int target) {
int l = 0, r = nums.size() - 1, mid;
while(l < r) {
if(nums[l] == target) return l;
else if(nums[r] == target) return r;
if(target >= nums[l]) {
mid = l + r + 1 >> 1;
if(nums[mid] <= target && nums[mid] >= nums[l]) l = mid;
else r = mid - 1;
} else {
mid = l + r + 1 >> 1;
if(nums[mid] <= target || nums[mid] >= nums[l]) l = mid;
else r = mid - 1;
}
}
return nums[l] == target ? l : -1;
}
};
easy
// The API isBadVersion is defined for you.
// bool isBadVersion(int version);
class Solution {
public:
int firstBadVersion(int n) {
if(isBadVersion(1)) return 1;
long l = 1, r = n, mid;
while(l < r) {
mid = l + r + 1 >> 1;
if(!isBadVersion(mid)) l = mid;
else r = mid - 1;
}
return l + 1;
}
};
高的一部分一定有峰值
class Solution {
public:
int findPeakElement(vector<int>& nums) {
int l = 0, r = nums.size() - 1, mid;
if(r == 0) return 0;
while(l < r) {
mid = l + r >> 1;
if(mid == 0 && nums[mid + 1] < nums[mid]) return mid;
else if(mid == (int)nums.size() - 1 && nums[mid - 1] < nums[mid]) return mid;
else if(nums[mid + 1] < nums[mid] && nums[mid - 1] < nums[mid]) return mid;
else if(nums[mid + 1] > nums[mid]) l = mid + 1;
else r = mid;
}
return l;
}
};
so difficult
需要对数据范围进行二分,不能对数组进行二分,这一点比较难想
class Solution {
public:
int findDuplicate(vector<int>& nums) {
int n = nums.size();
int l = 1, r = n - 1, mid, cnt;
while(l < r) {
mid = l + r >> 1;
cnt = 0;
for(auto x : nums) if(x >= l && x <= mid) cnt ++;
if(cnt > mid - l + 1) r = mid;
else l = mid + 1;
}
return l;
}
};
利用两段性判断
class Solution {
public:
int hIndex(vector<int>& citations) {
int l = 0, r = citations.size() - 1, n = citations.size(), mid;
if(citations[r] < 1) return 0;
while(l < r) {
mid = l + r >> 1;
if(n - mid > citations[mid]) l = mid + 1;
else r = mid;
}
return n - l;
}
};