27. 移除元素

题目描述

给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。

不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并 原地 修改输入数组。

元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。

0 <= nums.length <= 100 0 <= nums[i] <= 50 0 <= val <= 100

解题思路

线性算法,找到一个要移除的元素就和最后一个交换

#![allow(unused)]
fn main() {
struct Solution {}

impl Solution {
    pub fn remove_element(nums: &mut Vec<i32>, val: i32) -> i32 {
        let n = nums.len();
        if n == 0 { return 0 }
        // [i,j) 表示还需要处理的区间,在这个区间之外的都是无需处理的
        let mut i = 0;
        let mut j = n;
        while i < j {
            if nums[i] == val {
                j -= 1;
                nums[i] = nums[j];
            } else {
                i += 1;
            }
        }
        j as i32
    }
}
}

学习感想

一开始想的时候其实有不变量的思想在里面

写一下 双指针的版本

#![allow(unused)]
fn main() {
struct Solution {}
impl Solution {
    pub fn remove_element(nums: &mut Vec<i32>, val: i32) -> i32 {
        let mut a = 0;
        let mut b = 0;
        let n = nums.len();
        while b < n {
            if nums[b] == val { b += 1 }
            else {
                nums[a] = nums[b];
                a += 1;
                b += 1;
            }
        }
        a as i32
    }
}
}

std强大的标准库 Vec上retain方法

#![allow(unused)]
fn main() {
struct Solution {}
impl Solution {
    pub fn remove_element(nums: &mut Vec<i32>, val: i32) -> i32 {
        nums.retain(|&x| x != val);
        nums.len() as i32
    }
}

}

slow指针用来存储需要留下元素应该存放的地址,fast指针是当前处理的元素

#![allow(unused)]
fn main() {
struct Solution {}
impl Solution {
    pub fn remove_element(nums: &mut Vec<i32>, val: i32) -> i32 {
        let mut slow: usize = 0usize;    // the result elem
        let mut fast: usize = 0usize;    // the processing elem
        while fast < nums.len() {
            if nums[fast] == val { fast += 1usize }
            else {
                nums[slow] = nums[fast]; // move elem
                slow += 1usize;
                fast += 1usize;
            }
        }
        slow as i32
    }
}
}