Struct Solution

Source
pub struct Solution;

Implementations§

Source§

impl Solution

Source

pub fn length_longest_path(input: String) -> i32

用 Rust 的 Iterator 写函数式的解法。

先把输入拆分,因为每个片断都包含了文件名,路径深度和目录文件类型,对片断预处理。因为字符串表示是顺序表示的,所以前后之间是需要处理的。详细步骤说明:

  • \n 切分输入 split('\n')
  • 把每个 \t\tfile_name 映射成 (level, file_name_length, is_file),这里的 level0 开始(即根目录 level 为 0
    • 找到第一个不是 \t 的字符的位置,position 表示 \t 个数,即 level 层级,剩下的即文件名,我们取其长度即可,同时判断是否为文件(文件名中是否带 .
    • 如果没有 \t 说明是在根目录下的,即 level0
  • 计算每一个目录/文件名的长度(根据上一步生成的 tuple),因为每次分析都需要用到之前的路径在哪一层,所以需要用到 state 状态(栈),计算结果是每个目录/文件的长度,所以用 scan
    • 初始状态是 [],这里的状态表示上一次的父目录的绝对路径长度,即 [level_0_len, level_1_len, level_2_len, ...]
    • 进入到当前目录/文件,需要弹出上一次的父目录,直到 parents 里只剩当前目录/文件的父级(这里用 split_off(at) 来简化多次 pop()
    • 当前级别的目录/文件的长度就是剩下的 parents 里最后一个父目录的绝对路径长度和 + 当前文件名长度
    • 如果当前是目录,则当前目录长度 push 入栈,注意需要 + 1 表示算上 /
    • scan 函数的参数函数里,返回 (abs_len, is_file) (注:scan 函数相当于是 fold + map,或者说 map 带了个 state 状态)
  • 经过上一步,转换的结果已经变成 (abs_len, is_file) 了,只要过滤掉不是文件的项
  • 然后找出 max 就是结果了

这里除了 scan 中每一步过程中需要更新 parents 这个状态,其它地方没有任何的 mutable 变量。函数式编程的方式逻辑非常清晰,代码写起来也非常方便,可读性高,加上 immutable 使得安全性也非常好。关键是在 Rust 里用函数式的方法几乎不损失性能。

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.