关于快慢指针,之前有一个题目,{1,1,1,2,2,2,3,3,3,3}去重;但是现在我们要研究另一个问题

题目

{0,1,0,2,12,3},移动其中的0到最右侧,不能改变其他数值的相对位置;

分析

双指针并不一定全是快慢指针;如果这道题限定了时间复杂度是O(n);那么数组只能遍历一次;
此时重点一定是在元素==0上;
指针A,指向第一个0;
指针B,指向第一个不是0的数字;

0 1 0 2 12 3
指针A 指针B

让指针A和指针B指向的元素swap;

1 0 0 2 12 3
指针A 指针B

此时指针B向后移动,指向下一个不为0的数字,指针A也向后移动,指向第一个0

1 0 0 2 12 3
指针A 指针B

继续交换

1 2 0 0 12 3
指针A 指针B

继续交换,然后指针移动

1 2 0 0 12 3
指针A 指针B

之后只要按照这个规律移动数据,就能保证最后0都被移动到最右侧;
看起来很简单对吧….但是编码并不是这么简单的…
使用循环遍历数组如何保证循环的时候指针A和指针B在正确的位置;

  1. 指针A指向第一个元素,指针B指向第二个元素,进行第一轮判断,如果发现符合A->0,B->!0;交换
  2. 进入第二轮循环,进行判断,指针A是否指向的是0?指针B指向的是!0?如果不是的话,就要发生指针的移动了;指针A如果指向的还是0,指针A不移动;指针A指向的不是0,指针A向后移动一个元素;指针B如果指向的是0,那么指针B向后移动,如果指针B指向的不是0,不发生移动;
  3. 如果再第二轮循环中,A和B均满足条件,发生交换,如果有一个不满足,进入下一轮循环
  4. ……

    代码

    1. class Solution {
    2. public void moveZeroes(int[] nums) {
    3. //排序+环形替换?
    4. //并不行,因为给定数组不一定是顺序的..如果排序可能会导致新的数组元素相对顺序不同
    5. //使用双指针?
    6. if(nums.length==0)
    7. return;
    8. int guideIndex=1;
    9. int laterIndex=0;
    10. for(int i=1;i<nums.length;i++)
    11. {
    12. if(nums[laterIndex]==0&&nums[guideIndex]!=0)
    13. {
    14. //swap
    15. nums[laterIndex] = nums[guideIndex];
    16. nums[guideIndex] = 0;
    17. }
    18. if(nums[laterIndex]!=0)
    19. laterIndex++;
    20. if(nums[guideIndex]==0 || guideIndex<=laterIndex)
    21. guideIndex++;
    22. }
    23. }
    24. }

    误区

    一定要保证非0指针位于0指针的后边!!!