【LeetCode刷题】Day 2

题目1:283.移动零

题目分析:
将数组分为两个区间,左边为非零区间,右边为零区间。
-
数组划分,数组分块类问题。
- - 优先双指针解决
思路1:删除+尾插
C语言来实现的话就是,遍历遇到零,就后面的数向前覆盖,在补一个零。这里C++其实也是相同的思路,erase删除,push_back尾插。count的作用就是控制循环次数,免得重复操作。
代码实现:
class Solution {
public:
void moveZeroes(vector<int>& nums) {
auto it=nums.begin();
int count=0;
for(size_t i=0;i<nums.size()-count;)
{
if(nums[i]==0)
{
count++;
nums.erase(it+i);
nums.push_back(0);
}else i++;
}
return ;
}
};
思路2:双指针

将数据分为三个区域:非零区域,零区域,未处理区域。
开始可以想象为两个数组如何处理,cur遍历原数组,dest保存非零空间,再补0;
更具体一些:就是需要一个区间1:【0,dest】保持全为0,另一个cur指向的值不为零,就加入区间1。
其中dest初始值为-1,可以表达为开始【0,dest】中没有数据。从而避免了数组第一个数为0的情况。
代码实现:
class Solution {
public:
void moveZeroes(vector<int>& nums) {
int dest=-1,cur=0;
while(cur<nums.size())
{
if(nums[cur]!=0)
swap(nums[cur],nums[++dest]);
cur++;
}
return;
}
};
题目2:1089.复写零

题目分析:
思路1:暴力解法
遍历,是零就插入一个零,注意i需要加1,防止再次访问已处理过的零,插入后再尾删即可。
代码实现:
class Solution {
public:
void duplicateZeros(vector<int>& arr) {
for(size_t i=0;i<arr.size();i++)
{
if(arr[i]==0)
{
auto it=arr.begin();
arr.insert(it+i,1,0);
arr.pop_back();
i++;
}
}
return;
}
};
思路2:双指针

如果是异地操作相当的简单,但我们可以借鉴思路。
我们不能从前往后写,因为dest指针会跑到cur后面,导致后面未处理数据被覆盖。
所以我们从后往前写,但要去找cur的最后一个复写位置。所以还需要从前往后来一次双指针找位置。
但是位置的时候又会引发一个问题:cur最后一个位置是0,会导致dest位置越界(这一点需要考虑)
然后就可以开始复写了。
代码实现:
class Solution {
public:
void duplicateZeros(vector<int>& arr) {
int cur = 0, dest = -1;
//1.找位置
while (cur < arr.size()) {
if (arr[cur])
dest++;
else
dest += 2;
if (dest >= arr.size() - 1)
break;
cur++;
}
//2.处理边界值
if (dest == arr.size()) {
arr[arr.size() - 1] = 0;
cur--;
dest -= 2;
}
//3.复写操作
while (cur >= 0) {
if (arr[cur] == 0) {
arr[dest--] = 0;
arr[dest--] = 0;
cur--;
} else {
arr[dest--] = arr[cur--];
}
}
}
};
3798

被折叠的 条评论
为什么被折叠?



