全排列

求出N个数字的全排列
采用深度优先搜索
将每个数字看成树的节点
然后借助一个长度为N的数组,标识某个数字是否“被使用过”
当遍历到树的叶节点也就是深度为N时,将这一节点往上到根节点的路径保存到结果集中
大致遍历过程,举例 [1, 2, 3 ,4]
第一层可选1, 2, 3, 4,先选出1,往下一层
第二层可选2, 3, 4,先选出2
按这样到第四层时路径就是1-2-3-4为一种结果添加到结果
然后回溯到第三层,这一次第三层选出4,于是到第四层是路径为1-2-4-3
显然第三层的两种可能都选过了,再回溯到第二层
第二层这次选择2后面的3,然后按前面的规律到最后路径为1-3-2-4
然后老规矩返回到第三层选择4,最后第四层时路径为1-3-4-2
此时回溯到第三层时两种可能都选过了,再回溯到第二层选出4,重复上述过程
当第二层三种可能都选过时,返回到第一层选出2,以2为根节点重复上述过程

    public static List<List<Integer>> permutations(int n) {
        boolean[] used = new boolean[n];
        Deque<Integer> path = new LinkedList<>();
        List<List<Integer>> result = new LinkedList<>();
        dfs(n, path, result, used);
        return result;
    }

    /**
     * 深度优先搜索
     *
     * @param n      N个数
     * @param path   深度优先搜索的路径(中间结果)
     * @param result 结果集
     * @param used   记录各个数是否已经"取出"
     * @return void
     */
    private static void dfs(int n, Deque<Integer> path, List<List<Integer>> result, boolean[] used) {
        // 如果路径中的节点已经有n个, 则添加到结果集
        if (path.size() == n) {
            result.add(new LinkedList<>(path));
        } else {
            // 遍历N个数
            for (int i = 0; i < n; i++) {
                // 如果当前数未被"取出"
                if (!used[i]) {
                    // 标记为已"取出"
                    used[i] = true;
                    // 当前数添加到路径
                    path.addLast(i + 1);
                    dfs(n, path, result, used);
                    // 递归返回时将当前数重新标记为未"取出"
                    used[i] = false;
                    // 从路径中移出当前节点
                    path.removeLast();
                }
            }
        }
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值