给定一个数组nums,将所有 0移动到数组的末尾,同时保持非零元素的相对顺序。
请注意 ,必须在不复制数组的情况下原地对数组进行操作。
输入共两行。
第一行为两个个整数n,代表数组nums的长度。
第二行为n个整数nums0,nums1,...,numsn−1,数字之间以空格分隔。
输出操作后的数组,以空格分隔。
输入
5
0 1 0 3 12
输出
1 3 12 0 0
输入
1
0
输出
0
你能尽量减少完成的操作次数吗?
本题的目标是将数组中的所有 0
移动到数组末尾,并保持其他非零元素的相对顺序,同时要求 原地修改 数组,即不能复制额外的数组。这意味着我们需要用 双指针 和 原地交换 技巧来高效地解决问题。
我们可以使用 双指针法 来解决这个问题,其中一个指针 j
用来遍历整个数组,另一个指针 i
记录下一个应该放置非零元素的位置。具体做法如下:
i = 0
,用于记录非零元素应该存放的位置。i
位置,然后 i
向前移动。0
时,不做任何操作,继续遍历。0
会自动被放置到数组末尾。class Solution:
def moveZeroes(self, nums):
n = len(nums)
i = 0 # 记录非零元素应放置的位置
# 遍历数组,将非零元素移到前面
for j in range(n):
if nums[j] != 0:
nums[i], nums[j] = nums[j], nums[i] # 交换非零元素到前面
i += 1 # 移动非零元素位置索引
# 读入数据并调用函数
n = int(input().strip())
nums = list(map(int, input().split()))
Solution().moveZeroes(nums)
print(" ".join(map(str, nums)))
import java.util.*;
public class Main {
public class Solution {
public void moveZeroes(int[] nums) {
int i = 0; // 记录非零元素应存放的位置
// 遍历数组,将非零元素放到前面
for (int j = 0; j < nums.length; j++) {
if (nums[j] != 0) {
int temp = nums[i];
nums[i] = nums[j];
nums[j] = temp;
i++; // 更新非零存放位置
}
}
}
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt(); // 读取数组长度
int[] nums = new int[n];
for (int i = 0; i < n; i++) {
nums[i] = sc.nextInt();
}
Main main = new Main();
Solution solution = main.new Solution();
solution.moveZeroes(nums);
for (int i = 0; i < n; i++) {
System.out.print(nums[i] + (i < n - 1 ? " " : ""));
}
}
}
#include <iostream>
#include <vector>
using namespace std;
class Solution {
public:
void moveZeroes(vector<int>& nums) {
int i = 0; // 记录非零元素应存放的位置
// 遍历数组,将非零元素放到前面
for (int j = 0; j < nums.size(); j++) {
if (nums[j] != 0) {
swap(nums[i], nums[j]); // 交换非零元素到前面
i++; // 更新非零存放位置
}
}
}
};
int main() {
int n;
cin >> n; // 读取数组长度
vector<int> nums(n);
for (int i = 0; i < n; i++) {
cin >> nums[i];
}
Solution solution;
solution.moveZeroes(nums);
for (int i = 0; i < n; i++) {
cout << nums[i] << (i < n - 1 ? " " : "");
}
return 0;
}