移动零(力扣热题HOT100 之 力扣283)java

简介: 给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。请注意 ,必须在不复制数组的情况下原地对数组进行操作。

一、题目描述



给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。

请注意 ,必须在不复制数组的情况下原地对数组进行操作。


示例 1:

输入: nums = [0,1,0,3,12]

输出: [1,3,12,0,0]


示例 2:

输入: nums = [0]

输出: [0]

 

提示:

1 <= nums.length <= 104

-231 <= nums[i] <= 231 - 1

 

进阶:你能尽量减少完成的操作次数吗?


二、思路讲解


     

我们可以统计一下nums各个位置前面分别有多少0,有n个0就把这个位置上的数向前移动n位 ,再把数组末尾空缺的位置补上0即可。


三、Java代码实现



class Solution {
    public void moveZeroes(int[] nums) {
        int len = nums.length;
        int []ling = new int[len];  //记录第i位前面有几个0
        int sum = 0;                //记录一共有几个0
        //记录第i位前面有几个0
        for(int i=0; i<len; i++){
            if(nums[i] == 0){
                ling[i] = -1;
                sum++;
            } else {
                ling[i] = sum;
            }
        }
        //前面有几个0就向前移动几位
        for(int i=0; i<len; i++){
            if(nums[i] != 0){
                nums[i-ling[i]] = nums[i];
            }
        }
        //把后面补上0
        for(int i=len-1; i>=len-sum; i--){
            nums[i] = 0;
        }
    }
}



时间复杂度:        O(N)

空间复杂度:        O(N)


三、代码优化



时间复杂度已经足够优秀了,但是操作次数过多;空间复杂度还不够完美,能否减少空间的使用呢?


这就需要用到双指针了。

       1、开始时两指针同时在最左边,然后左右指针同时右移去找零。

       2、当左指针指零时,右指针右移去找非零。

       3、当找到非零时,交换;

       4、左右指针再同时右移去找零(重复1,2,3直到右指针达到末尾)

class Solution {
    public void moveZeroes(int[] nums) {
        int n = nums.length, left = 0, right = 0;
        while (right<n) {
            //如果左指针指非零,无需交换,双指针后移
            while(right<n && nums[left]!=0){
                left++;
                right++;
            }
            //如果左指针指零,那么右指针后移去找非零,然后交换
            while(right<n && nums[right]==0){
                right++;
            }
            if(right<n){
                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;
    }
}


可以简化一下代码:

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;
    }
}



时间复杂度:        O(N)

空间复杂度:        O(1)

相关文章
|
12天前
|
算法 Java
[Java·算法·简单] LeetCode 283. 移动零
[Java·算法·简单] LeetCode 283. 移动零
17 2
|
24天前
|
算法 Java Go
【经典算法】LeetCode 67. 二进制求和(Java/C/Python3/Golang实现含注释说明,Easy)
【经典算法】LeetCode 67. 二进制求和(Java/C/Python3/Golang实现含注释说明,Easy)
10 2
|
24天前
|
存储 算法 Java
【经典算法】Leetcode 141. 环形链表(Java/C/Python3实现含注释说明,Easy)
【经典算法】Leetcode 141. 环形链表(Java/C/Python3实现含注释说明,Easy)
11 2
|
24天前
|
算法 Java Go
【经典算法】LeetCode 69. x 的平方根(Java/C/Python3/Golang实现含注释说明,Easy)
【经典算法】LeetCode 69. x 的平方根(Java/C/Python3/Golang实现含注释说明,Easy)
8 1
|
24天前
|
Java
P9242 [蓝桥杯 2023 省 B] 接龙数列JAVA,边权为1的最短路问题,洛谷P9242 [蓝桥杯 2023 省 B] 接龙数列​编辑力扣1926.迷宫离入口最近的出口力扣433.
P9242 [蓝桥杯 2023 省 B] 接龙数列JAVA,边权为1的最短路问题,洛谷P9242 [蓝桥杯 2023 省 B] 接龙数列​编辑力扣1926.迷宫离入口最近的出口力扣433.
|
24天前
|
算法 Java Go
【经典算法】LeetCode 392 判断子序列(Java/C/Python3/Go实现含注释说明,Easy)
【经典算法】LeetCode 392 判断子序列(Java/C/Python3/Go实现含注释说明,Easy)
20 0
|
24天前
|
算法 Java Go
【经典算法】LeetCode 1103 分糖果 II(Java/C/Python3实现含注释说明,Easy)
【经典算法】LeetCode 1103 分糖果 II(Java/C/Python3实现含注释说明,Easy)
19 0
|
24天前
|
存储 算法 Java
【经典算法】LeetCode112. 路径总和(Java/C/Python3/Go实现含注释说明,Easy)
【经典算法】LeetCode112. 路径总和(Java/C/Python3/Go实现含注释说明,Easy)
11 0
|
24天前
|
存储 算法 Java
【经典算法】LeetCode 125. 验证回文串(Java/C/Python3实现含注释说明,Easy)
【经典算法】LeetCode 125. 验证回文串(Java/C/Python3实现含注释说明,Easy)
10 0
|
24天前
|
算法 Java Go
【经典算法】LeetCode 100. 相同的树(Java/C/Python3/Go实现含注释说明,Easy)
【经典算法】LeetCode 100. 相同的树(Java/C/Python3/Go实现含注释说明,Easy)
9 0