好久不敲代码了,复健!
今日任务
LeetCode704.二分查找
二分分为两种写法,找左边界、和右边界
class Solution {
public:
int search(vector<int>& nums, int target) {
int N = nums.size();
int left = 0, right = N - 1, mid;
// 如果target有很多个,那么找的左边界,因为只要>=target那么就左移右边界[r = (r+l)/2]
// while (left < right) {
// mid = (left + right) >> 1;
// if (nums[mid] >= target) right = mid;
// else left = mid + 1;
// }
// 下面是找右边界的方法
while (left < right) {
mid = (left + right + 1) >> 1; // 中间+1为了防止left与right差为1时不更新
if (nums[mid] <= target) left = mid;
else right = mid - 1;
}
if (nums[left] == target) return left;
return -1;
}
};
LeetCode27. 移除元素
第一种方法:排序+二分
O
(
n
l
o
g
n
)
O(nlogn)
O(nlogn)
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
if (!nums.size()) return 0;
sort(nums.begin(), nums.end());
// sort(nums.begin(), nums.begin() + nums.size());
// for (auto it : nums) cout << it << endl;
// 左边界resR
int left = 0, right = nums.size() - 1, mid, resL, resR; // resL与resR是等于val的区间边界
while (left < right) {
mid = (left + right) >> 1;
if (nums[mid] >= val) right = mid;
else left = mid + 1;
}
if (nums[left] == val) {
resL = left;
} else { // 说明没有相等的
return nums.size();
}
// 寻找右边界resR
left = 0, right = nums.size() - 1;
while (left < right) {
mid = (left + right + 1) >> 1;
if (nums[mid] <= val) left = mid;
else right = mid - 1;
}
resR = right;
// 删除数组中元素
for (int i = resL, k = resR + 1; k < nums.size(); ++i, ++k) {
nums[i] = nums[k];
}
nums.resize(nums.size() - (resR - resL + 1));
return nums.size();
}
};
第二种方法:双指针
O
(
n
)
O(n)
O(n)
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
int left = 0, n = nums.size(); // left指向下一个需要赋值的位置,right指向下一个需要与val比较的位置
for (int right = 0; right < n; ++right) {
if (nums[right] != val) { // 如果right指向位置与val不相等,则赋值给left指向位置,同时left自增1,保证区间[0, left)内的值都不等于val
nums[left++] = nums[right];
}
}
return left;
}
};