YSMull
<-- algorithm



原题链接

回溯法

impl Solution {
    pub fn partition(s: String) -> Vec<Vec<String>> {
        let mut res = vec![];
        Solution::partition_0(&s, 0, 0, &mut vec![], &mut res);
        return res;
    }

    pub fn partition_0(s: &String, i: usize, j: usize, cur: &mut Vec<String>, res: &mut Vec<Vec<String>>) {
        if j == s.len() {
            if i == j {
                res.push(cur.clone());
            }
            return;
        }
        if Solution::is_palindrome(&s[i..=j]) {
            cur.push(String::from(&s[i..=j]));
            Solution::partition_0(s, j + 1, j + 1, cur, res);
            cur.pop();
        }
        Solution::partition_0(s, i, j + 1, cur, res);
    }

    fn is_palindrome(s: &str) -> bool {
        let mut i = 0 as i32;
        let mut j = (s.len() - 1) as i32;
        while i <= j {
            if s.chars().nth(i as usize).unwrap() != s.chars().nth(j as usize).unwrap() {
                return false;
            }
            i += 1;
            j -= 1;
        }
        return true;
    }
}

递归的时候不产生 clone

耍了一波生命周期标注,让递归的时候不产生 clone, 最后把 Vec<Vec<&str>> 转成 Vec<Vec<String>> 的时候,会把原本在递归的时候的 clone 的开销补回来。但没想到提交代码总耗时还增加了(116ms -> 140~160ms),本地压测时也发现耗时增加了。

impl Solution {
    pub fn partition(s: String) -> Vec<Vec<String>> {
        let mut res = vec![];
        Solution::partition_0(&s, 0, 0, &mut vec![], &mut res);
        let x: Vec<_> = res.into_iter().map(|i| i.into_iter().map(|j| String::from(j)).collect::<Vec<String>>()).collect();
        return x;
    }

    pub fn partition_0<'a>(s: &'a String, i: usize, j: usize, cur: &mut Vec<&'a str>, res: &mut Vec<Vec<&'a str>>) {
        if j == s.len() {
            if i == j {
                res.push(cur.clone()); // 这里 clone 的是 Vec<&str>,免不了的
            }
            return;
        }
        if Solution::is_palindrome(&s[i..=j]) {
            cur.push(&s[i..=j]); // 这里去掉了 clone,性能确实提高了
            Solution::partition_0(s, j + 1, j + 1, cur, res);
            cur.pop();
        }
        Solution::partition_0(s, i, j + 1, cur, res);
    }

    fn is_palindrome(s: &str) -> bool {
        let mut i = 0 as i32;
        let mut j = (s.len() - 1) as i32;
        while i <= j {
            if s.chars().nth(i as usize).unwrap() != s.chars().nth(j as usize).unwrap() {
                return false;
            }
            i += 1;
            j -= 1;
        }
        return true;
    }
}

尝试了把转换的操作用明显性能更高的方式写,发现仍然会更慢。

pub fn partition(s: String) -> Vec<Vec<String>> {
    let mut res = vec![];
    Solution::partition_0(&s, 0, 0, &mut vec![], &mut res);

    let mut collector = Vec::with_capacity(res.len());

    for r in res.iter() {
        let mut v = Vec::with_capacity(r.len());
        for i in r {
            v.push(i.to_string());
        }
        collector.push(v);
    }

    // let x: Vec<_> = res.into_iter().map(|i| i.into_iter().map(|j| String::from(j)).collect::<Vec<String>>()).collect();
    return collector;
}