力扣283:移动零

43 阅读2分钟

1.移动零

1.1我的方法

刚开始读错题目,认为非零元素的相对顺序是按大小排序,解法一并附上,感兴趣可自行阅读

int count = 0;//记录0的个数
        for (int num : nums) {
            //先对数组中0的个数进行记录
            if (num == 0) {
                count++;
            }
        }



        boolean flag = false;//移位标记
        for (int i = 0; i < nums.length; i++) {
            if(i+1!=nums.length&&!flag&&nums[i]==0&&nums[i+1]!=0){
                //说明为连续0的最后一个0,可以开始移位
                flag = true;
                continue;//当前循环不进行移位
            }
            if(flag){
                //可以开始移位
                nums[i-count]=nums[i];
            }
        }
        //最后将数组后count个元素赋值为0
        for (int i = count; i != 0; i--) {
            nums[nums.length-i]=0;
        }

以下为正确题解:

TreeSet<Integer> set = new TreeSet<>();
for (int i = 0; i < nums.length; i++) {
    if(nums[i]==0){
        //如果当前元素是0,与后方第一个不为0的元素交换顺序
        set.add(i);//先记录下0元素的索引
    }
    if(!set.isEmpty() &&nums[i]!=0){
        //如果set中已经记录多个,从最小的开始交换
        nums[set.first()]=nums[i];
        nums[i]=0;
        set.remove(set.first());               
        set.add(i);//当前元素变为0,加入set
    }
}

思路:使用TreeSet来保存0元素的索引,遍历数组,如果当前元素为0,加入set进行处理,如果元素不是0,判断set中是否有需要处理的0元素,如果有,交换索引最小的0元素和当前元素的顺序,则当前元素变为0,加入set中

1.2双指针法

public void moveZeroes(int[] nums) {
    int slow = 0; // 慢指针:下一个非零元素的写入位置
    
    for (int fast = 0; fast < nums.length; fast++) {
        if (nums[fast] != 0) {
            // 将非零元素移到慢指针位置(只操作非零元素)
            nums[slow] = nums[fast];
            // 如果位置不同,将原位置设为0(避免覆盖非零数据)
            if (slow != fast) {
                nums[fast] = 0;
            }
            slow++; // 慢指针后移
        }
    }
}

思路:定义快慢指针指向第一个元素,慢指针遇到0元素停下,快指针遇到非0元素就和慢指针的元素交换

视频讲解:www.bilibili.com/video/BV1tZ…