双指针
- 🎈1.移动零
- 🔭1.1题目
- 🔭1.2算法原理
- 🔭1.3编写代码
- 🎈2.复写零
- 🔭2.1题目
- 🔭2.2算法原理
- 🔭2.3编写代码
🎈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++;elsedest += 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--;}}}
};