Rust:算法题:移动0

问题描述

给定一个数组 nums,编写一个函数将所有0移动到数组的末尾,同时保持非零元素的相对顺序。重要的是要在不复制数组的情况下原地对数组进行操作。 leetcode链接

示例说明:
  • 示例 1:

    • 输入:nums = [0,1,0,3,12]
    • 输出:[1,3,12,0,0]
  • 示例 2:

    • 输入:nums = [0]
    • 输出:[0]
约束条件:
  • 1 <= nums.length <= 10^4
  • -2^31 <= nums[i] <= 2^31 - 1

解题思路

一般像数组,有序,并且将其进行数字移动的操作都可以考虑双指针法,因为通常来说都可以降低时间复杂度,如果不用双指针法,可能就需要两层循环,但是用双指针法,一次循环就可以达到两层循环的效果,非常好用!

算法方法

为了解决这个问题,我们采用双指针技巧,通过两个指针 slowfast 来有效地区分非零元素和零。方法可以分为两个主要步骤:

  1. 第一遍扫描 - 将非零元素移动到左边:

    • 使用 fast 遍历数组时,我们用 slow 来跟踪下一个非零元素应该放置的位置。每次在 fast 位置遇到一个非零元素,我们就将其值复制到 slow 指向的位置,然后增加 slow
    • 这个步骤确保所有非零元素都移动到数组的开头,并保持它们原有的顺序。
  2. 第二遍扫描 - 将剩余位置填充为零:

    • slow 指针的位置开始(现在指向最后一个非零元素的下一个位置),我们将数组的其余部分填充为零。

Rust 代码实现

rust 复制代码
impl Solution {
    pub fn move_zeroes(nums: &mut Vec<i32>) {
        let mut slow = 0_usize;
        let mut fast = 0_usize;
        while fast < nums.len() {
            if nums[fast] != 0 {
                nums[slow] = nums[fast];
                slow += 1;
            }
            fast += 1;
        }
        while slow < nums.len() {
            nums[slow] = 0;
            slow += 1;
        }
    }
}

复杂度分析

  • 时间复杂度: 由于算法对数组进行了两次遍历,因此时间复杂度为线性时间复杂度, O(n),其中n是数组中的元素个数。
  • 空间复杂度: 由于操作是就地进行的,并且只使用了恒定数量的额外空间,所以空间复杂度为 O(1)。

为什么双指针方法有效?

双指针方法之所以在"移动零"问题中特别有效,是因为它允许我们在单次或极少的遍历中完成对数组的修改,同时保持非零元素的相对顺序。这种方法使用两个指针(在本问题中是slowfast)分别跟踪特定条件下的元素位置,从而达成如下目的:

  • slow指针:标记了当前已处理序列的末尾,即下一个非零元素应该放置的位置。

  • fast指针:用于遍历数组,寻找非零元素。

  • 这种区分使得算法能够在fast指针寻找到非零元素时,立即将其移动到slow指针的位置,从而将非零元素集中到数组的前端,而不需要额外的数组来存放非零元素或多次遍历数组。

  • 减少赋值操作 :通过只在fast指针找到非零元素时才进行赋值操作,减少了不必要的赋值次数。如果fastslow指向相同的元素,实际上没有必要做赋值操作,因为它们都是非零的,这避免了自赋值。

  • 避免多余的遍历 :一旦所有非零元素都被移动到数组的前面,剩下的位置必定都是零。因此,第二次遍历从slow指针开始,直接将剩余的部分填充为零,无需再次检查这些元素是否为零。Pomelo_刘金。转载请注明原文链接。感谢!

相关推荐
Dontla39 分钟前
Rust泛型系统类型推导原理(Rust类型推导、泛型类型推导、泛型推导)为什么在某些情况必须手动添加泛型特征约束?(泛型trait约束)
开发语言·算法·rust
梦想画家42 分钟前
精通rust宏系列教程-入门篇
rust·元编程·rust宏
Ttang231 小时前
Leetcode:118. 杨辉三角——Java数学法求解
算法·leetcode
喜欢打篮球的普通人1 小时前
rust模式和匹配
java·算法·rust
java小吕布1 小时前
Java中的排序算法:探索与比较
java·后端·算法·排序算法
杜若南星1 小时前
保研考研机试攻略(满分篇):第二章——满分之路上(1)
数据结构·c++·经验分享·笔记·考研·算法·贪心算法
路遇晚风1 小时前
力扣=Mysql-3322- 英超积分榜排名 III(中等)
mysql·算法·leetcode·职场和发展
Neophyte06081 小时前
C++算法练习-day40——617.合并二叉树
开发语言·c++·算法
木向2 小时前
leetcode104:二叉树的最大深度
算法·leetcode