全排列

求出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();
                }
            }
        }
    }

你可能感兴趣的:(java,算法,dfs,数据结构)