力扣283. 移动零

移动零:Java解法详解

来源:283. 移动零

目录

移动零:Java解法详解

题目

详解 

方法一:双指针(官方解法)

思路及解法

代码

代码说明

 方法二(简单做法)

思路及解法

代码

知识点:增强for

基本语法

1. 遍历数组

2. 遍历集合

3. 只读循环

4. 无法获取索引

5. 性能考虑

6. 适用范围

示例代码


题目

给定一个数组 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

详解 

方法一:双指针(官方解法)

该方法的核心在于思维训练,建议深入学习掌握。

思路及解法

使用双指针,左指针指向当前已经处理好的序列的尾部,右指针指向待处理序列的头部。

右指针不断向右移动,每次右指针指向非零数,则将左右指针对应的数交换,同时左指针右移。

注意到以下性质:

左指针左边均为非零数;

右指针左边直到左指针处均为零。

因此每次交换,都是将左指针的零与右指针的非零数交换,且非零数的相对顺序并未改变。

代码
class Solution {
    /**
     * 将数组中的所有零元素移动到数组的末尾,同时保持非零元素的相对顺序。
     *
     * @param nums 输入的整数数组
     */
    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++; // 右指针右移,继续遍历数组
        }
    }

    /**
     * 交换数组中两个指定位置的元素。
     *
     * @param nums 输入的整数数组
     * @param left 左侧元素的索引
     * @param right 右侧元素的索引
     */
    public void swap(int[] nums, int left, int right) {
        int temp = nums[left]; // 临时变量保存左指针位置的元素
        nums[left] = nums[right]; // 将右指针位置的元素赋值给左指针位置
        nums[right] = temp; // 将临时保存的元素赋值给右指针位置
    }
}
代码说明
  • moveZeroes 方法通过双指针技术遍历数组,将非零元素逐步移动到数组的前端。
  • swap 方法用于交换数组中两个指定位置的元素,这里用于将非零元素交换到前面来。
  • 使用两个指针 left 和 rightright 指针遍历整个数组,而 left 指针用于标记下一个非零元素应放置的位置。
 方法二(简单做法)
思路及解法

我们可以通过计数器记录零元素的数量。遇到非零元素时直接存入数组,遍历结束后在数组末尾补上相应数量的零即可。

代码
import java.util.Arrays;

class Solution {
    public void moveZeroes(int[] nums) {
//        int pc = 0;
//        int ac = 0;
//        //new一个int数组
//        int[] num2 = new int[nums.length];
//        for (int num : nums) {
//            if (num != 0) {
//                //将不为0的元素添加到num2
//                num2[pc] = num;
//                pc++;
//            }
//        }
//        //num2的值给num
//        for (int num : num2) {
//            nums[ac] = num;
//            ac++;
//        }
        int pc = 0;
        for(int num : nums){
            if(num != 0){
                nums[pc++] = num;
            }
        }
        for (int i = pc; i < nums.length; i++ ){
            nums[i] = 0;
        }
    }
}
//测试用例
public class Main {
    public static void main(String[] args) {
        int[] nums = {0, 1, 0, 3, 12};
        Solution solution = new Solution();
        solution.moveZeroes(nums);
        //输出nums数组
        String result = Arrays.toString(nums); // 使用Arrays.toString()方法
        System.out.println(result);
    }
}

知识点:增强for

基本语法

增强的 for 循环的语法如下:

for (元素类型 元素变量名 : 数组或集合) {
    // 循环体
}

1. 遍历数组

增强的 for 循环可以非常简洁地遍历数组中的所有元素,而不需要手动处理索引和数组长度。例如:

int[] numbers = {1, 2, 3, 4, 5};
for (int number : numbers) {
    System.out.println(number);
}

2. 遍历集合

增强的 for 循环同样适用于遍历集合(如 ListSet 等)。例如:

List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
for (String name : names) {
    System.out.println(name);
}

3. 只读循环

增强的 for 循环是只读的,这意味着你不能通过循环修改数组或集合中的元素。如果你需要修改元素,应使用传统的 for 循环或迭代器。

4. 无法获取索引

增强的 for 循环不提供对当前元素索引的直接访问。如果需要索引,应使用传统的 for 循环。

5. 性能考虑

增强的 for 循环在大多数情况下性能与传统的 for 循环相似,因为它在内部使用迭代器进行遍历。

6. 适用范围

增强的 for 循环可以用于任何实现了 Iterable 接口的对象,包括所有集合类。

示例代码

以下是一个完整的示例,展示了如何使用增强的 for 循环遍历数组和集合:

public class EnhancedForLoopExample {
    public static void main(String[] args) {
        // 遍历数组
        int[] numbers = {1, 2, 3, 4, 5};
        for (int number : numbers) {
            System.out.println(number);
        }

        // 遍历集合
        List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
        for (String name : names) {
            System.out.println(name);
        }
    }
}

收起

通过这些知识点,你可以更好地理解和使用增强的 for 循环来简化代码,提高可读性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值