排列树与子集树

Posted oldhands

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了排列树与子集树相关的知识,希望对你有一定的参考价值。

  • 子集树

    子集树主要求解当前集合的所有子集,是算法中的基本思想指导。参考代码如下,以求解字符串的子集串为例子:

    

 1 /**
 2      * 子集树
 3      * @param S 字符数组
 4      * @param t 初始为0
 5      */
 6     public void ZJTree(char[] S , int t){
 7         if(t > S.length - 1){ // 叶子节点
 8             System.out.println(String.valueOf(S).replace("#",""));
 9         }else{ //非叶子结点
10             ZJTree(S,t+1);
11             char m = S[t];
12             S[t] = ‘#‘; //表示删除S[t]
13             ZJTree(S,t+1);
14             S[t] = m; //主要是在递归的过程中 S传递的是引用 不会对S现场进行保护 因此手动回复 或者上面使用 ZJTree(S.clone(),t+1);
15         }
16     }

    此代码可以结合二叉树的深度(见图)遍历进行理解,每个节点有 0(不选) 1(选择)两种方式,在实际过程中,可用合理的方式进行标记

    技术图片

    以上代码中,我们使用中间缓存 m 保存当前将要删除的节点,在递归之后进行恢复,原因是 S传递的是引用 不会对S现场进行保护 因此手动回复 或者上面使用 ZJTree(S.clone(),t+1);

 

  • 排列树

    排列树主要求解当前集合的所有全排列,是算法中的基本思想指导。参考代码如下,以求解字符串的全排列为例子:

 1 /**
 2      * 排列树
 3      * @param S 字符数组
 4      * @param t 初始为0
 5      */
 6     public void PLTree(char[] S , int t){
 7         if(t > S.length - 1){ // 子节点
 8             System.out.println(S);
 9         }else{ //非子结点
10             for(int i = t;i < S.length;i++){ // 多叉树遍历
11                 swap(S,t,i); //两次swap 主要保证 第一个数与任何一位进行交换一次
12                 PLTree(S,t + 1);
13                 swap(S,t,i);
14             }
15         }
16     }
17     public void swap(char[] S , int l , int r){
18         char t = S[l];
19         S[l] = S[r];
20         S[r] = t;
21     }

以上代码可以结合多叉树的深度遍历继续理解,不同的是此多叉树每一层的不同层每一个子节点的数目是递减的,使用for + 参数t 来进行控制,每层节点的字节点依次递减    技术图片  

    代码中swap() 两次主要作用:for + swap 保证在S[t...length]中,将每一个节点作为头节点进行递归处理(将头节点与每一个节点进行交换),也就是:

    001: a b c(递归 b c)          b a c(递归a c)           c b a(递归b a)

以上是关于排列树与子集树的主要内容,如果未能解决你的问题,请参考以下文章

5.10 决策树与ID3算法

两种典型的解空间树:子集树和排列树

子集树和排列树

决策树与随机森林

一文读懂胜者树与败者树

LeetCode1734. 解码异或后的排列 / 剑指 Offer 36. 二叉搜索树与双向链表 / 剑指 Offer 37. 序列化二叉树