题目描述:
给定一个数组 nums
,编写一个函数将所有 0
移动到数组的末尾,同时保持非零元素的相对顺序。
示例:
输入:[0,1,0,3,12]
输出:[1,3,12,0,0]
说明:
- 必须在原数组上操作,不能拷贝额外的数组。
- 尽量减少操作次数
这道题我首先想到的思路:就是类似于冒泡排序一样,将0看作最大/最小的数,进行判断如果是0,就将相邻元素交换位置,这样从头到尾经过‘比较’(判断是否为0),0就全部沉底。满足题意,没有拷贝额外数组。但是这种方法有种弊端就是时间复杂度很大是O(n^2),数组大时,效率是一个很大的问题。
第二种思路就是:类似于我曾经做过的一道题中的方法,就是用“双指针法”,所谓双指针法也就是说,定义两个指针变量,i,j;i负责遍历原数组,j负责将满足条件(不是0的元素)的元素按顺序赋值给数组。然后原数组前j个元素就是满足条件的(不是0的元素)元素,剩下的位数中就用0填充即可。这种方式也特别好理解(这种方法有一点很重要,就是两个指针其中一个指针需要跑在前面(指向原数组的指针),一个指针需要跑在后面(指向当前存储位置的指针),),执行次数少,效率高,时间复杂度O(n).
思路介绍完了,具体看代码:
第一种思路:
public class 移动零 {
public static void main( String[] args ) {
移动零 m=new 移动零 ( );
int[] a={0 , 1 , 0 , 3 , 12};
m.moveZeroes ( a );
}
// 第一种方法,双重for循环(类似冒泡排序,挨个比较,是0就交换)
public void moveZeroes( int[] nums ) {
int t;
for (int i=0; i < nums.length; i++) {
for (int j=i + 1; j < nums.length; j++) {
//如果是0,就交换相邻的元素,直到0沉底
if (nums[i] == 0) {
t=nums[i];
nums[i]=nums[j];
nums[j]=t;
}
}
}
for (int i=0; i < nums.length; i++) {
System.out.print ( nums[i] + " " );
}
}
执行结果:
执行用时:
第二种思路:
// 第二种方法就是用双指针法,遍历数组,i指针用来遍历原数组,j指针将不重复的元素顺序添加的原数组中,(类似与简单中的那个移除指定元素这道题的思路,异曲同工的感觉)空出了的位用0填充
public void moveZeroes(int[] nums) {
int j=0;
for (int i=0; i < nums.length; i++) {
if (nums[i] != 0) {
nums[j++]=nums[i];
}
}
// 这个地方i=j因为,j之前全是非0元素,从0---j-1,所以剩与的空位就只有j-原数组长度之间,将这之间的元素赋值为0即可。
for (int i=j; i < nums.length; i++) {
{
nums[i]=0;
}
}
for (int i=0;i<nums.length;i++){
System.out.print(nums[i]+" ");
}
}
执行用时:
类似题目:如“移除指定元素”这道题也是用双指针解决的:
详细请看我的博客:https://blog.csdn.net/weixin_37850160/article/details/86633275
2019-2-25记录,今天虽然感觉有点困,但是很充实。继续加油。