YSMull
<-- algorithm



原题链接

回溯法(原地 swap)

这个是网上流传的最简洁的版本,但是不是很好理解,这里用到了 swap 方法,直接在原数组中整理数据。

区间 [0, idx) 表示已经排列好了的部分,每一次需要选择 idx 可以放置的元素,直到 idx == len 的时候表示某个排列结束了。

对于 [idx, len) 的任何元素,都可以通过 swap 方法放置到 idx 的位置。

impl Solution {
    pub fn permute(mut nums: Vec<i32>) -> Vec<Vec<i32>> {
        let mut result = vec![];
        Solution::permute0(&mut nums, 0, &mut result);
        return result
    }

    fn permute0<T:PartialEq + Clone>(arr: &mut Vec<T>, idx: usize, result: &mut Vec<Vec<T>>) {
        let len = arr.len();
        if idx == len {
            result.push(arr.clone());
            return;
        }
        for i in idx..len {
            arr.swap(i, idx);
            Solution::permute0(arr, idx + 1, result);
            arr.swap(i, idx);
        }
    }
}

回溯法(使用 collector)

这个方法是我做了带重复元素的全排列后重新回来写这道题使用的。
代码中 idx 表示的是 collector 数组的当前长度,当 collector 数组排列满了之后,就得到了一个排列。
这里需要引入一个 vis 数组来记录 arr 中哪些元素已经参与排列了,每一次从 arr 中选择出所有还没有参与排列的元素 push 进 collector 参与排列,同时标记这个元素被使用过了。

impl Solution {
    pub fn permute(mut nums: Vec<i32>) -> Vec<Vec<i32>> {
        let mut vis: Vec<bool> = (0..nums.len()).map(|x| false).collect();
        let mut result = vec![];
        Solution::permutation_collector(&mut nums, 0, &mut vis, &mut vec![], &mut result);
        return result;
    }

    pub fn permutation_collector<T: PartialEq + Copy>(arr: &mut Vec<T>, idx: usize, vis: &mut Vec<bool>, collector: &mut Vec<T>, res: &mut Vec<Vec<T>>) {
        if collector.len() == arr.len() {
            res.push(collector.clone());
            return;
        }
        for i in 0..arr.len() { //  arr 中所有还没有参与排列的元素都可以 push 进 collector
            if vis[i] {
                continue;
            }
            collector.push(arr[i]);
            vis[i] = true;
            Solution::permutation_collector(arr, idx + 1, vis, collector, res);
            collector.pop();
            vis[i] = false;
        }
    }
}

非回溯法(next_permutation)

LeetCode 47