Solutions to high-frequency interview questions of LeetCode in C++17, taking into account both efficiency and comprehensibility.
O(log n)
,应当使用二分查找,STL 提供了如下二分查找函数
class Solution {
public:
vector<int> searchRange(vector<int>& nums, int target) {
if (!binary_search(begin(nums), end(nums), target)) {
return {-1, -1};
}
int l = lower_bound(begin(nums), end(nums), target) - begin(nums);
int r = upper_bound(begin(nums), end(nums), target) - begin(nums) - 1;
return {l, r};
}
};
int binarySearch(vector<int>& nums, int target) {
int l = 0;
int r = size(nums); // 右边界为最后一个元素的后一位置
while (l != r) { // 只要左右区间不重合,就说明范围中有元素
int m = l + (r - l) / 2; // 防溢出所以不写 (l + r) / 2
if (nums[m] == target) {
return m; // 找到则返回
} else if (nums[m] > target) {
r = m; // 下一范围右边界不包含 m
} else {
l = m + 1; // 下一范围左边界不包含 m
}
} // 结束时 l == r,[l, r) 内不包含任何元素
return -1; // 未找到返回 -1
}
int binarySearch(vector<int>& nums, int target) {
int l = 0;
int r = size(nums) - 1; // 右边界为最后一个元素
while (l <= r) { // 包含右边界,所以应该有等号
int m = l + (r - l) / 2;
if (nums[m] == target) {
return m;
} else if (nums[m] > target) {
r = m - 1;
} else {
l = m + 1;
}
}
return -1;
}
int lowerBound(vector<int>& nums, int target) {
int l = 0;
int r = size(nums);
while (l != r) {
int m = l + (r - l) / 2;
if (nums[m] >= target) {
r = m; // 满足条件则继续左压
} else {
l = m + 1;
}
} // r 是满足条件的右边界,最后一次左压结束时 r 恰好是第一个满足条件的位置
// 比如数组只有一个元素且满足条件,则左压一次 l 和 r 都为 0
// r 恰好落在第一个满足条件的位置
// 结束时l == r,下面用到的 l 都可以换成 r
if (l == size(nums)) { // 没有左压过
return -1; // 不会有满足条件的值
}
return l;
}
template <typename F>
int binarySearch(vector<int>& nums, int n, F check) {
int l = 0;
int r = size(nums);
while (l != r) {
int m = l + (r - l) / 2;
if (check(nums[m])) { // 满足条件则继续左压
r = m;
} else { // 不满足条件则右压
l = m + 1;
}
}
if (l == size(nums)) { // 没有左压过
return -1; // 不会有满足条件的值
}
return l;
}
int upperBound(vector<int>& nums, int target) {
int l = 0;
int r = size(nums);
while (l < r) {
int m = l + (r - l) / 2;
if (nums[m] > target) {
r = m;
} else {
l = m + 1;
}
}
if (l == size(nums)) {
return -1;
}
return l;
}
class Solution {
public:
vector<int> searchRange(vector<int>& nums, int target) {
int a = lowerBound(nums, 0, size(nums), target);
int b = upperBound(nums, 0, size(nums), target);
return {a, b};
}
int lowerBound(vector<int>& nums, int l, int r, int target) {
while (l != r) {
int m = l + (r - l) / 2;
if (nums[m] >= target) {
r = m;
} else {
l = m + 1;
}
}
return l < size(nums) && nums[l] == target ? l : -1;
}
int upperBound(vector<int>& nums, int l, int r, int target) {
while (l != r) {
int m = l + (r - l) / 2;
if (nums[m] > target) {
r = m;
} else {
l = m + 1;
}
}
return l > 0 && nums[l - 1] == target ? l - 1 : -1;
}
};