【Leetcode46】全排列

 

全排列

  • 给定一个不含重复数字的数组 nums ,返回其 所有可能的全排列 。你可以 按任意顺序 返回答案。

示例 1:

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

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

  • 输入:nums = [1]
  • 输出:[[1]]

提示:

  • 1 <= nums.length <= 6
  • -10 <= nums[i] <= 10
  • nums 中的所有整数 互不相同

思考

  1. 这是典型的回溯算法问题。因为求排列组合,需要一步一步递归构建所有可能的排列。
  2. 关键是要理解回溯算法的思想 - 路径的选择和回退。要不断地选择,递归探索下一个可能的分支,再退回到上一步,探索其他分支。
  3. 需要定义递归函数,作为回溯函数,传入当前的 intermediate path。
  4. 终止条件是路径长度等于数组长度,说明找到了一个全排列。
  5. 在递归函数内部,需要遍历数组,选择一个数字加入路径,递归调用,然后再删除以回退。
  6. 需要剪枝,也就是重复元素的去重处理。
  7. 需要一个结果 list 来保存找到的所有排列,在终止时addToList。

题解

class Solution {
    public List<List<Integer>> permute(int[] nums) {
        List<List<Integer>> res = new ArrayList<>();
        // 定义回溯方法
        backtrack(nums, new ArrayList<>(), res);
        return res;
    }

    // 回溯算法
    private void backtrack(int[] nums, List<Integer> tempList, List<List<Integer>> res) {
        // 路径长度等于数组长度时,找到一种排列
        if(tempList.size() == nums.length) {
            res.add(new ArrayList<>(tempList));
            return;
        }

        // 遍历数组中的每个元素作为路径元素
        for(int n : nums) {
            // 如果元素已存在路径中,跳过
            if(tempList.contains(n)) continue;

            // 添加元素到路径
            tempList.add(n);
            // 回溯
            backtrack(nums, tempList, res);
            // 回溯后删除元素
            tempList.remove(tempList.size() - 1);
        }
    }
}

本文遵守 Attribution-NonCommercial 4.0 International 许可协议。 Attribution-NonCommercial 4.0 International