代码随想录算法训练营第一天| 704.二分查找、27.移动元素
LeetCode704 二分查找
题目链接:https://leetcode.cn/problems/binary-search/
讲解视频:https://www.bilibili.com/video/BV1fA4y1o715/
自己实现
class Solution {
public:
int search(vector<int>& nums, int target) {
int l = 0, r = nums.size() - 1;
while(l < r) {
int mid = (l + r) >> 1;
if(nums[mid] >= target) r = mid;
else l = mid + 1;
}
if(nums[r] == target) return l;
else return -1;
}
};
我的方法其实也不错
左闭右闭
class Solution {
public:
int search(vector<int>& nums, int target) {
int l = 0, r = nums.size() - 1;
while(left <= right) { // 左闭右闭允许左右两端点相等
int mid = left + (right - left) / 2; // 防止溢出
if(nums[mid] > target) { // [...target ... mid ...]
r = mid - 1;
}else if(nums[mid] < target){ // [...mid ...target ...]
l = mid + 1;
}else return mid; // 找到目标,直接返回
}
return - 1;
}
};
左闭右开
class Solution {
public:
int search(vector<int>& nums, int target) {
int l = 0, r = nums.size() - 1;
while(left < right) { // 左闭右开不允许左右两端点相等
int mid = left + (right - left) / 2; // 防止溢出
if(nums[mid] > target) { // [...target ... mid ...]
r = mid; // 不包括右端点,可以直接等于mid
}else if(nums[mid] < target){ // [...mid ...target ...]
l = mid + 1;
}else return mid; // 找到目标,直接返回
}
return - 1;
}
};
总结
- 循环不变量,编写代码的时候要一直遵循开闭区间的规则;
- 防止
r + l
发生越界,采用l + ( r - l) / 2
这种写法;
LeetCode27 移除元素
暴力解法
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
int len = nums.size();
for(int i = 0; i < len; i++) { // 这里也用len来判断,长度是不断在减小的
if(nums[i] == val) { // 找到目标数,开始向迁移
for(int j = i + 1; j < len; j++) { // 将目标数后面一个开始
nums[j - 1] = nums[j];
}
i--;// i + 1的数字到了下标为 i 的位置上,为了不漏掉倒退一位
len--; // 长度减少一位
}
}
return len;
}
};
双指针
双指针含义
- 快指针:寻找新数组的元素 ,新数组就是不含有目标元素的数组
- 慢指针:指向更新新数组下标的位置
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
int s = 0, f = 0;
for(; f < nums.size(); f++) {
if(nums[f] != val)
nums[s++] = nums[f];
}
return s;
}
};
总结
- 当时先写除了双指针的方法,写暴力的时候遇见了些问题,
- 一个是
for(int i = 0; i < len; i++)
这里要用len
,因为长度是一直在变的 - 第二个是忘记了
i--
这样会漏掉下一个数字;
- 一个是
- 双指针法关键是理解快慢指针的意义。
- 快指针是去寻找新的插入数组的元素
- 慢指针是维护当前最新的数组