一.题目
给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。 示例: 输入: [0,1,0,3,12] 输出: [1,3,12,0,0] 说明: 必须在原数组上操作,不能拷贝额外的数组。 尽量减少操作次数。
二.解题思路
本题的解题思路主要还是用的快速排序的思想,首先要确定一个待分割的元素做中间点X,然后把所有小于等于X的元素放在左边,大于X的元素放在右边。 这的中间点就是0本身,所以实现起来比快速排序简单很多,我们使用两个指针i和j,只要nums[i]!=0,我们就交换nums[i]和nums[j]
三.答案 一
public void moveZeroes(int[] nums) { if(nums==null) { return; } //两个指针i和j int j = 0; for(int i=0;i<nums.length;i++) { //当前元素!=0,就把其交换到左边,等于0的交换到右边 if(nums[i]!=0) { int tmp = nums[i]; nums[i] = nums[j]; nums[j++] = tmp; } } }答案 二
//优化版 public void moveZeroes(int[] nums) { int length; if (nums == null || (length = nums.length) == 0) { return; } int j = 0; for (int i = 0; i < length; i++) { if (nums[i] != 0) { if (i > j) {// #1 nums[j] = nums[i]; nums[i] = 0; } j++; } } }四.难点详解
一.题目理解起来并不难,解法一注意的点就一个: j++是j先参与本行语句的其他运算,其他运算完成之后,j再自加1。。++j是j先自加1,再参与其他运算 这个概念别弄混了就行。
二.答案二主要是针对答案一的优化,其实优化的地方就是#1处。它避免了数组开头是非零元素的交换也就是阻止(i==j)时交换。 当i > j 时,只需要把 i 的值赋值给j 并把原位置的值置0。同时这里也把交换操作换成了赋值操作,减少了一条操作语句,理论上能更节省时间。
五.结语 路漫漫其修远兮,吾将上下而求索,哈撒给…