持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第14天,点击查看活动详情
1、写在前面
大家好,我是翼同学,这里是【水滴计划 | 刷题日志】
每日两题,拒绝摆烂。
2、内容
2.1、题目一:删除有序数组中的重复项
链接:26. 删除有序数组中的重复项 - 力扣(LeetCode)
(1) 描述
(2) 举例
(3) 解题
用双指针解题即可。
代码如下:
class Solution {
public:
int removeDuplicates(vector<int>& nums) {
// 1. 定义两个指针,分别指向数组的第一个元素和第二个元素
int left = 0;
int right = 1;
// 2. 遍历数组,将不重复的元素移到数组的左侧
while(right < nums.size()) {
if(nums[left] != nums[right]) {
nums[left+1] = nums[right];
left++;
}
right++;
}
// 3. 最后放回数组长度
return left+1;
}
};
这个解题思路其实很容易理解,可以看作去吃自助餐,数组中每个编号都代表一种食品,有个吃货决定,必须将每道菜都吃一遍,此时如果遇到没见过的编号,就将其拉到左边,按顺序排好,如果遇到见过的编号,则直接忽略。
举个例子:
- 比如数组中元素为:
0, 1, 1, 6, 9, 9 - 此时保持第一个数字不要动,然后往后面看,数字是
1,没见过,于是将1排在0的后面,接着再往后看,数字是1,1已经见过了,就直接忽略不管,再往后看,看到新面孔6,就将其拉到左边,排在0, 1的后面,以此类推。 - 最后结果为
0, 1, 6, 9
2.2、题目二:长度最小的子数组
链接:209. 长度最小的子数组 - 力扣(LeetCode)
(1) 描述
(2) 举例
(3) 解题
首先,暴力解法来一遍。
很可惜,执行结果超出时间限制。
为了降低时间复杂度,我们利用一个for循环来替代两个for循环的遍历操作,也就是双指针解法。这里的子数组更新操作也可以看成滑动窗口解法。
代码如下:
class Solution {
public:
int minSubArrayLen(int s, vector<int>& nums) {
// 1. 存放运算结果
int result = INT32_MAX;
// 2. 子数组元素之和
int sum = 0;
// 3. 子数组的长度
int subL = 0;
// 4. 子数组起始位置
int i = 0;
// 5. 遍历数组,j指向子数组的终止位置
for (int j = 0; j < nums.size(); j++) {
// 5.1 计算当前子数组元素之和
sum += nums[j];
// 5.2 动态更新子数组起始位置i
while (sum >= s) {
// 取到当前子数组的长度
subL = (j - i + 1);
// 通过比较,判断当前子数组是否符合条件
if(result >= subL) {
result = subL;
}
// 更新当前子数组的元素之和
sum -= nums[i];
// 更新子数组的起始位置i
i++;
}
}
// 6. 返回答案
if(result == INT32_MAX) {
// 说明result没有被赋值过,意味着没有符合条件的子数组
return 0;
}else {
// 返回运算结果
return result;
}
}
};
- 提问:为什么时间复杂度是 ?
- 记录:时间复杂度取决于每个元素被操作的次数,不是说
for循环中加上while循环就会导致时间复杂度为,每个元素其实在滑动窗口后进来被操作一次,出去又被操作一次,因此时间复杂度为,即。
3、写在最后
好了,今天就刷到这里,明天再来。