持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第22天,点击查看活动详情
前言
题目来源
题目介绍
给定一个数组
nums,编写一个函数将所有0移动到数组的末尾,同时保持非零元素的相对顺序。请注意 ,必须在不复制数组的情况下原地对数组进行操作。
输入: nums = [0,1,0,3,12]
输出: [1,3,12,0,0]
题目分析
根据题目意思,已知一个数组,将数组的元素如果是0,将它往后移动一位。那么反过来理解,如果这个元素不是0,那么就将它往前移动一位交换位置,如果第一个元素就不是0,那么就是0和0交换,不变。如果第二个是0,第三个不是0,那么第三个和第二个交换位置,这样那么为0的元素就往后移动了一位。
题目解答
class Solution {
public void moveZeroes(int[] nums) {
int n=nums.length;
//定义一个位置递增的变量
int num=0;
for(int i=0;i<n;i++){
//如果不为0,那么交换位置
if(nums[i]!=0){
int temp=nums[i];
nums[i]=nums[num];
nums[num]=temp;
//每次碰到不为0的元素 ,累加1。这样如果是第一个是0,第二个是0,第三个不是0,第四个不是0,那么i=2的时候,将nums[2]和nums[0]交换,i=3的时候,将nums[3]和nums[1]交换
num++;
}
}
}
}
如上代码验证
这么一看 这个方式的效率还是比较低一些。
官方答案验证
class Solution {
public void moveZeroes(int[] nums) {
int n = nums.length, left = 0, right = 0;
while (right < n) {
if (nums[right] != 0) {
swap(nums, left, right);
left++;
}
right++;
}
}
public void swap(int[] nums, int left, int right) {
int temp = nums[left];
nums[left] = nums[right];
nums[right] = temp;
}
}
原理差不多,记录位置交换顺序,包装一个方法,也节省了内存。
看记录,有题友也提供了更简便的方法
public void moveZeroes(int[] nums) {
int index = 0;
for (int num : nums) {
if (num != 0) {
nums[index++] = num;
}
}
for (int i = index; i < nums.length; i++) {
nums[i] = 0;
}
}
这个方式运行如下
这样跑起来的更高效,内存也更少。利用的原理是,先把不为0的元素赋值依次从下标0开始的位置,这样就有一个变量记录到了多少个元素不为0,依次按顺序排放了。
接下来把剩余位置的元素,依次赋值0。这样就完全符合题目要求了。相对这个方式更容易理,也更稳妥。
总结
解题方式看来都是有比较多种的,多看看别人的分析,自己也能领会更多的解题思路。