趣味算法题

越刷越上头的趣味算法题
帅旋
关注
充电
IT宅站长,技术博主,架构师,全网id:arthinking。

快慢指针热门算法题:移动零

发布于 2024-03-12 | 更新于 2024-08-21

题目[1]

给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。

请注意 ,必须在不复制数组的情况下原地对数组进行操作。

示例 1:

1
2
输入: nums = [0,1,0,3,12]
输出: [1,3,12,0,0]

示例 2:

1
2
输入: nums = [0]
输出: [0]

提示:

  • 1 <= nums.length <= 104
  • -231 <= nums[i] <= 231 - 1

**进阶:**你能尽量减少完成的操作次数吗?

参考题解

题目分析

这个算法题目的目:把一个数组中所有的0移动到数组的末尾,同时保持非零元素的相对顺序

解题思路

我们可以使用一个简单的双指针技巧来解决这个问题。具体可以使用快慢指针来追踪遍历:

  1. 快指针(fast):遍历数组,用于寻找非零元素。
  2. 慢指针(slow):指向当前已处理序列的尾部的下一个位置,这个位置是下一个非零元素应当存放的位置。

遍历过程中,每次当快指针指向的元素非0时:

  • 如果快慢指针不重合,说明可以把快指针指向的值往慢指针移动,处理方法交换快慢指针指向的元素,并且慢指针前进;

  • 如果快慢指针重合,说明目前遍历的序列都是非0,慢指针和快指针同时前进。

这样,所有非零元素都被移到了数组的前面,且保持了它们的相对顺序,然后数组剩余的位置填充0。

下面是用Java实现的代码示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class MoveZeroes {
public void moveZeroes(int[] nums) {
int slow = 0;
for (int fast = 0; fast < nums.length; fast++) {
if (nums[fast] != 0) {
// 当快慢指针指向的元素不相同时,交换这两个元素
if (slow != fast) {
// 交换快慢指针指向的元素
int temp = nums[slow];
nums[slow] = nums[fast];
nums[fast] = temp;
}
// 慢指针前进
slow++;
}
}
}
}

进一步优化

可以发现,当nums[fast] != 0并且slow != fast的时候,那么此刻的nums[slow]一定是0,可以简化代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class MoveZeroes {
public void moveZeroes(int[] nums) {
int slow = 0;
for (int fast = 0; fast < nums.length; fast++) {
if (nums[fast] != 0) {
// 当快慢指针指向的元素不相同时,交换这两个元素
if (slow != fast) {
// 交换快慢指针指向的元素
nums[slow] = nums[fast];
nums[fast] = 0;
}
// 慢指针前进
slow++;
}
}
}
}

References


  1. 283. 移动零 ↩︎

本文作者: 帅旋

本文链接: https://www.itzhai.com/columns/dsa/move-zeroes.html

版权声明: 版权归作者所有,未经许可不得转载,侵权必究!联系作者请加公众号。

×
IT宅

关注公众号及时获取网站内容更新。

请帅旋喝一杯咖啡

咖啡=电量,给帅旋充杯咖啡,他会满电写代码!

IT宅

关注公众号及时获取网站内容更新。