🎈1.移动零
🔭1.1题目
给定一个数组nums,编写一个函数将所有0移动到数组的末尾,同时保持非零元素的相对顺序。请注意,必须在不复制数组的情况下原地对数组进行操作。
示例一:
输入:nums = [0,1,0,3,12]
输出:[1,3,12,0,0]
示例二:
输入:nums = [0]
输出:[0]
注意:必须在不复制数组的情况下原地对数组进行操作!
🔭1.2算法原理
数组划分,数组分块
这里我们提出双指针算法(利用数组下标来充当指针)
cur:从左往右扫描数组,遍历数组
dest:已处理的区间内,非零元素的最后一个位置
cur从前往后的遍历过程中,遇到0元素,cur++
;遇到非0元素:swap(dest+1,cur);dest++;cur++;
🔭1.3编写代码
class Solution
{
public:
void moveZeros(vector<int>& nums)
{
for (int cur = 0, dest = -1; cur < nums.sizes(); cur++)
{
if (nums[cur])
swap(nums[++dest], nums[cur]);
}
}
};
🎈2.复写零
🔭2.1题目
给你一个长度固定的整数数组arr,请你将该数组中出现的每个零都复写一遍,并将其余的元素向右平移。注意:不要在超过该数组长度的位置写入元素,请对输入的数组就地进行上述修改,不要从函数返回任何东西。
🔭2.2算法原理
解法:双指针算法:先根据异地操作,然后优化成双指针下的就地操作。
(1).先找到最后一个“复写”的数:先判断cur位置的值,决定dest向后移动一步或者两步,判断一下dest是否已经到结束为止,cur++
(2).从后向前完成复写操作
🔭2.3编写代码
class Solution
{
public:
void duplicateZeros(vector<int>& arr)
{
//找到最后一个复写的数
int cur = 0, dest = -1, n = arr.size();
while (cur < n)
{
if (arr[cur])
dest++;
else
dest += 2;
if (dest >= n - 1)
break;
cur++;
}
//处理边界情况
if (dest == n)
{
arr[n - 1] = 0;
cur--;
dest -= 2;
}
//从后向前完成复写操作
while (cur >= 0)
{
if (arr[cur])
arr[dest--] = arr[cur--];
else
{
arr[dest--] = 0;
arr[dest--] = 0;
cur--;
}
}
}
};