001_移动零
给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。
请注意 ,必须在不复制数组的情况下原地对数组进行操作。
示例 1:
输入: nums = [0,1,0,3,12]
输出: [1,3,12,0,0]
示例 2:
输入: nums = [0]
输出: [0]
提示:
1 <= nums.length <= 104-231 <= nums[i] <= 231 - 1
进阶: 你能尽量减少完成的操作次数吗?
题解:
算法原理:双指针算法
定义两个指针cur和dest,这里的指针采用的数组下标来充当指针。
两个指针的作用:
cur:从左往右遍历数组;
dest:已处理区间内,非零元素的最后一个位置;
用这两个指针进行区间划分三个区间:
非0区间:[0, dest]
0区间:[dest + 1, cur - 1]
待处理区间:[cur, n- 1]
操作过程:
cur从左往右遍历过程中:
① 遇到0元素:cur++;
② 遇到非0元素:
dest++; swap(dest, cur);
代码:
public:
void moveZeroes(vector<int>& nums) {
int dest = -1, cur = 0; //双指针
for(; cur < nums.size(); ++cur)
{
if(nums[cur] != 0)
{
dest++;
swap(nums[dest], nums[cur]);
}
}
}
};
002_复写零
给你一个长度固定的整数数组 arr ,请你将该数组中出现的每个零都复写一遍,并将其余的元素向右平移。
注意:请不要在超过该数组长度的位置写入元素。请对输入的数组 就地 进行上述修改,不要从函数返回任何东西。
示例 1:
输入: arr = [1,0,2,3,0,4,5,0]
输出: [1,0,0,2,3,0,0,4]
解释: 调用函数后,输入的数组将被修改为:[1,0,0,2,3,0,0,4]
示例 2:
输入: arr = [1,2,3]
输出: [1,2,3]
解释: 调用函数后,输入的数组将被修改为:[1,2,3]
提示:
1 <= arr.length <= 1040 <= arr[i] <= 9
题解:
算法原理:双指针算法
定义两个指针cur和dest,这里的指针采用的数组下标来充当指针。
① 先判断cur位置的值;
② cur遇到非0元素,dest走一步;cur遇到0元素,dest走两步;
③ 判断一下dest是否到结束位置,若dest没有结束,cur++。
特殊情况:
dest到下标n的位置,已经越界:
下标n-1的位置置为0,cur--,dest -= 2;
最后,“从右往左”完成复写0操作。
代码:
public:
void duplicateZeros(vector<int>& arr) {
// 找复写数
int cur = 0, dest = -1;
while (cur <= arr.size())
{
if (arr[cur])
{
// 非0,dest向后走一步
dest++;
}
else
{
// 0,dest向后走两步
dest += 2;
}
// dest没到边界,cur再往后走一步
if (dest < arr.size() - 1)
cur++;
else
break;
}
// 复写0
while (cur >= 0)
{
// 处理特殊情况
if (dest == arr.size())
{
arr[--dest] = arr[cur--];
--dest;
}
if (arr[cur])
{
// 非0,赋值之后,cur和dest向前各走一步
arr[dest--] = arr[cur--];
}
else
{
// 0,赋值给0,dest向前走两步,cur走一步
arr[dest--] = 0;
arr[dest--] = 0;
cur--;
}
}
}
};