系列文章目录
【代码随想录】Day1 数组理论基础,704. 二分查找,27. 移除元素
前言
希望在接下来的60天时间内能跟随代码随想录将Leetcode速刷一次。
之前没有用C++刷过题目,为了增进C++写码功底,故此次刷题使用C++。
704. Binary Search
Source: 704. Binary Search
Note:以前刷的时候没有仔细思考过边界的含义,要注意 写题的时候要始终坚持 区间的定义 : 究竟是左闭右闭还是左闭右开?
左闭右闭
- 在while循环中我们应该让判断条件的区间满足区间定义。此时left=right 是一个有意义的区间,所以应该是 left <= right的判断条件。
- 在每次更新区间边界的时候,target和mid比大小,如果不等的话,区间边界应该更新为mid+1或者mid-1,原因是mid已经和target比较过了,应该保证每次更新后的区间始终去除不存在target的数组范围。
- right初始化为nums.size() - 1因为右闭
class Solution {
public:
int search(vector<int>& nums, int target) {
int left = 0;
int right = nums.size() - 1;
while (left <= right) {
int mid = left + (right - left)/2;
if (nums[mid] < target) {
left = mid + 1;
} else if (nums[mid] > target) {
right = mid - 1;
} else {
return mid;
}
}
return -1;
}
};
左闭右开
- left=right 是一个无意义的区间,所以应该是 left < right
- 在每次更新区间边界的时候,target和mid比大小,如果不等的话,区间边界应该更新为mid(若右边界更新)或者mid+1(若左边界更新)。原因是如果右边界更新,由于右开,所以mid不包含在区间内。如果左边界更新,由于左闭,mid包含在区间内,而 mid > target, 所以此时左边界应该更新为mid+1,这样才能让新区间不包含已经判断过的mid
- right初始化为nums.size()因为右开
class Solution {
public:
int search(vector<int>& nums, int target) {
int left = 0;
int right = nums.size();
while (left < right) {
int mid = left + (right - left)/2;
if (nums[mid] < target) {
left = mid + 1;
} else if (nums[mid] > target) {
right = mid;
} else {
return mid;
}
}
return -1;
}
};
左开右闭
一般使用较少,也能实现
Tips::先判断不等而不是相等,因为不等是更经常发生的,可以减少运算量提高速度
27. Remove Element
Source: 27. Remove Element
Note:题目给定一个数组,和一个指定数字,要求在原数组中进行修改,使得前k位数字正好为数组删掉指定数字后的排序,k到nums.size()之间的下标不做判断
这道题目以前刷过很多类似的,很容易想到快慢指针,快指针对数组遍历,慢指针对应“最终需要的答案数组部分”的遍历。
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
int p1 = 0;
int p2 = 0;
while (p1 < nums.size()) {
if (nums[p1] != val) {//如果快指针的数和指定数不同,将快指针的数字复制到目标的位置
nums[p2] = nums[p1];
p1++;
p2++;
}else{//如果相同,则跳过这个数字
p1++;
}
}
return p2;
}
};
C++运行0ms 击败100%
Tips:
vector.erase()是O(n)的操作,将整个vector元素前移
总结
今天主要详细理解了区间定义对二分法的重要性和对快慢指针法进行复习,并且学习了CSDN博客的撰写,今后会提高博客撰写效率。
DAY1 Finished 撒花~