Java中如何将递归生成的集合排列存入Set以完成BST结构对比
核心问题根源
你当前实现的combos排列生成方法,仅在递归触达终止条件时执行控制台打印操作,没有设计将生成的排列结果传递到主流程外部容器的通道,因此主方法始终无法拿到完整的排列集合做后续BST插入、对比操作。
另外原排列生成方法存在一个隐蔽小Bug:递归触达终止条件时没有执行返回操作,会继续执行后续的元素遍历、栈修改逻辑,既增加冗余计算,也可能引发栈状态异常。
实现存储逻辑的改造步骤
1. 定义统一的排列收集容器
排列本身是有序的整数序列,不能直接存入普通无序列表结构,需要在主方法中定义专门的容器,用来承载所有生成的排列结果:
// 容器元素为每个独立的排列序列,用List存储保证元素顺序固定 List<List<Integer>> allPermutations = new ArrayList<>();
2. 改造排列生成方法的入参与终止逻辑
给原combos方法新增收集容器的入参,在递归终止(栈长度等于目标排列长度)时,必须对当前栈的元素做值拷贝,再存入收集容器——绝对不能直接传入Stack对象的引用,因为Stack是递归全程动态修改的可变对象,后续递归回退时会执行pop清空元素,直接存引用只会得到动态变化的同一对象,无法保存独立的排列快照。
改造后的排列生成方法代码:
public static void combos(Set<Integer> items, Stack<Integer> stack, int size, List<List<Integer>> allPermutations) { if (stack.size() == size) { // 拷贝当前栈元素生成独立排列对象,存入收集容器 List<Integer> currentPerm = new ArrayList<>(stack); allPermutations.add(currentPerm); // 保留原有打印逻辑也可兼容之前的运行效果 System.out.println(currentPerm); // 触达终止条件必须return,避免后续冗余执行 return; } Integer[] itemz = items.toArray(new Integer[0]); for (Integer i : itemz) { stack.push(i); items.remove(i); combos(items, stack, size, allPermutations); items.add(stack.pop()); } }
3. 主方法调整调用逻辑
在主方法中调用排列生成方法时,把提前初始化好的收集容器作为入参传入,等递归全流程执行完成后,allPermutations里就完整保存了所有之前在控制台打印的排列结果,可以直接在主方法中遍历取用。
调整后的调用代码:
// 原有初始化测试集合、栈的逻辑保持不变 int size = 4; Set<Integer> tes = new LinkedHashSet<>(size); Stack<Integer> stack = new Stack<>(); Random r = new Random(); while (tes.size() < size) { tes.add(r.nextInt(10)); } System.out.println(tes); System.out.println("possible combinations"); // 初始化排列收集容器 List<List<Integer>> allPermutations = new ArrayList<>(); // 传入收集容器调用排列生成方法 combos(tes, stack, tes.size(), allPermutations);
后续BST对比的实现说明
拿到完整排列集合后,就可以按需求选取任意两个排列做独立BST插入对比:
- 每次对比前重新实例化两棵全新的空
BST对象,不要复用全局定义的bst1、bst2,避免残留节点值干扰对比结果 - 把第一个排列的元素按原顺序逐个插入第一棵BST
- 把第二个排列的元素按原顺序逐个插入第二棵BST
- 调用BST自带的
levelOrder()层级遍历方法,对比两棵树的遍历输出序列是否一致,即可判断不同插入顺序是否会生成结构相同的BST
内容的提问来源于stack exchange,提问作者Liza Darwesh
相关产品推荐
相关产品推荐

