排列树与子集树
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)
以上是关于排列树与子集树的主要内容,如果未能解决你的问题,请参考以下文章
LeetCode1734. 解码异或后的排列 / 剑指 Offer 36. 二叉搜索树与双向链表 / 剑指 Offer 37. 序列化二叉树