题目
给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。
请注意 ,必须在不复制数组的情况下原地对数组进行操作。
示例 1:
输入: nums = 0,1,0,3,12
输出: 1,3,12,0,0
示例 2:输入: nums = 0
输出: 0
提示:1 <= nums.length <= 104
-231 <= numsi <= 231 - 1
进阶:你能尽量减少完成的操作次数吗?
解法1:直接复制
- 直接找一个新的数组,按顺序复制非零数字即可,空出来的位置为0
java
public class Move_Zero {
public static void moveZeroes(int[] nums) {
int[] news = new int[nums.length];
int j = 0;
for (int i: nums){
if (i != 0){
news[j] = i;
j++;
}
}
System.out.println(Arrays.toString(news));
}
}
解法2:双指针交换
- 寻找到第一个为0的位置
- 在该位置之后寻找第一个不为0的数据
- 二者进行交换
bash
{0,1,0,0,12};arr[0]为0,下一个不为0的是arr[1],交换
{1,0,0,0,12};arr[1]为0,下一个不为0的是arr[4],交换
{1,12,0,0,0};arr[2]为0,下一个不为0的是不存在,遍历到末尾,直接break
{0,3,4};arr[0]为0,下一个不为0的是arr[1],交换
{3,0,4};arr[1]为0,下一个不为0的是arr[2],交换
{3,4,0};break
java
public class Move_Zero {
public static void moveZeroes(int[] nums){
for (int i = 0; i < nums.length; i++) {
if (nums[i] == 0) {//i的位置是第一个为0的位置
int first_not_zero = i;
//向后依次遍历首个不为0的元素
for (first_not_zero = i; first_not_zero < nums.length; first_not_zero++) {
if (nums[first_not_zero] != 0) {
//寻找到后进行交换
int temp = nums[first_not_zero];
nums[first_not_zero] = 0;
nums[i] = temp;
break;
}
}
if (first_not_zero == nums.length) break;//之后判断都是0,直接break
}
}
System.out.println(Arrays.toString(nums));
}
}
如果是这样的一个数组0,0,0,0,1,2,3,4,这样交换的方法,每次遇到0都需要向后遍历,时间复杂度为O(n^2)
解法3:双指针交换
- 针对上面的解法,可以做一个改动,即第二个寻找非零位置的指针,不进行从头遍历
- 首先找到第一个零元素位置和其后面的第一个非零元素位置
- 交换后,非零元素寻找下一个非零元素,直至数组末尾
更为简洁的代码
- 初始位置全部设为0
- 当前位置 i 只要遍历到不是 0 的,就和 j 进行交换
bash
java
public void moveZeroes(int[] nums) {
int j = 0; // 指向第一个0(或待交换位置)
for (int i = 0; i < nums.length; i++) {
if (nums[i] != 0) {
if (i != j) {
int temp = nums[i];
nums[i] = nums[j];
nums[j] = temp;
}
j++;
}
}
}
解法4:双指针覆盖补零
- 上面的解法好像每次遍历交换有些复杂,可以直接进行数字的覆盖,
这样只需要遍历一遍数组 - 首部指针用来指向所有非零的元素,全遍历指针用来寻找非零的数字作为要覆盖的数据
- 全遍历指针遍历完成后,首部指针后面的元素全为0
java
public class Move_Zero {
public static void moveZeroes(int[] nums){
int first = 0;
for(int i=0;i<nums.length;i++){
if(nums[i]!=0){
nums[first++]=nums[i];
}
}
for(int i=first;i<nums.length;i++){
nums[i]=0;
}
System.out.println(Arrays.toString(nums));
}
}