【CT】LeetCode手撕—46. 全排列


题目


1- 思路

模式识别

  • 模式1不含重复数字的数组 nums ——> 任意顺序 可能的全排列 ——> 回溯
  • 模式2全排列 ——> 排列问题,不同于组合问题 ——>
  • 回溯每次相当于枚举一个结果集,当当层结果集的长度为 nums.length 时候收集结果

为什么排列问题需要用 used 数组?

  • 排列问题关注元素的顺序,即[1, 2]和[2, 1]被视为两个不同的排列。为了生成所有可能的排列,每个元素在每个特定的排列中只能出现一次,但可以在不同的排列中重复出现。
  • used数组的作用: 在排列问题中,used数组用来跟踪每个元素是否已经被当前排列使用。这是因为每个元素在生成单个排列时只能使用一次,但在生成不同的排列时可以重新使用。used数组确保在构建每个排列时,每个元素只被选择一次。

组合问题中

  • 组合问题不关注元素的顺序,即[1, 2]和[2, 1]被视为相同的组合。组合问题通常要求选择一个子集,不考虑元素的排列顺序。
  • 组合问题中的递归调用: 在组合问题中,通常不需要used数组,因为一旦选择了一个元素,就不需要再次选择它。递归调用时,通常将下一个元素的索引传递给递归函数,这样就自然地避免了重复使用同一个元素。
  • 组合问题通过传递 startIndex 来避免递归过程中重复取元素的问题。

回溯三部曲

  • 1.回溯参数返回值
    • 参数为:参数 nums
    • 返回值为 void,通过定义 List<List<Integer>> res 收集结果
  • 2.终止条件 && 结果收集
    • 当 当前 iterm.size() == nums.length 收集结果并 return;
  • 3.回溯搜索的遍历过程
    • for(int i = 0; i<nums.length;i++)

2- 实现

⭐46. 全排列——题解思路

在这里插入图片描述

class Solution {

    List<List<Integer>> res = new ArrayList<>();
    List<Integer> path = new ArrayList<>();
    boolean[] used;
    public List<List<Integer>> permute(int[] nums) {
        used = new boolean[nums.length];
        Arrays.fill(used,false);
        backTracing(nums);
        return res;
    }


    public void backTracing(int[] nums){
        // 1.终止条件
        if(path.size() == nums.length){
            res.add(new ArrayList(path));
            return ;
        }

        // 2. 回溯
        for(int i = 0 ; i < nums.length ;i++){
            if(used[i]){
                continue;
            }
            used[i] = true;
            path.add(nums[i]);
            backTracing(nums);
            used[i] = false;
            path.removeLast();
        }
    
    }
}

3- ACM实现

public class permute {

    static List<List<Integer>> res = new ArrayList<>();
    static List<Integer> path = new ArrayList<>();
    static boolean[] used;
    public static List<List<Integer>> permuteFunction(int[] nums){
        used = new boolean[nums.length];
        Arrays.fill(used,false);
        backTracing(nums);
        return res;
    }

    public static void backTracing(int[] nums){
        // 2.终止条件
        if(nums.length==path.size()){
            res.add(new ArrayList<>(path));
        }
        // 3.回溯遍历搜索过程
        for(int i = 0; i < nums.length;i++){
            if(used[i]){
                continue;
            }
            used[i] = true;
            path.add(nums[i]);
            backTracing(nums);
            used[i] = false;
            path.remove(path.size()-1);
        }
    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        System.out.println("输入全排列数组长度");
        int n = sc.nextInt();
        System.out.println("输入数组值");
        int[] nums = new int[n];

        for(int i = 0 ; i < n;i++){
            nums[i] = sc.nextInt();
        }

        System.out.println("全排列的结果是");
        List<List<Integer>> forRes = permuteFunction(nums);
        System.out.println(forRes.toString());
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值