Java HashSet全排列生成程序打印空白行问题排查求助
我仔细看了你的代码,问题主要出在排列结果的存储方式上,另外还有一个小问题会影响排列生成的正确性,具体如下:
1. 核心问题:直接引用栈对象导致存储的排列被清空
在extendPermutation的base case(remainingItems.isEmpty())中,你直接把permutationSoFar这个Stack对象添加到allPermutations里:
allPermutations.add(permutationSoFar);
但Stack是引用类型,你添加的只是栈的内存地址,而不是当前栈里元素的副本。后续递归返回后执行的permutationSoFar.pop()会把栈里的元素一个个移除,最终所有存在allPermutations里的列表都会变成空的——这就是为什么你只看到空白行的原因。
修复方法
把栈的内容复制到一个新的列表中再添加,比如用ArrayList来保存当前栈的状态:
allPermutations.add(new ArrayList<>(permutationSoFar));
这样每个排列都会被独立存储,后续的pop操作不会影响已经保存的结果。
2. 次要问题:alternateSet复用导致排列生成错误
你当前把alternateSet的创建放在for循环外面:
Set<String> alternateSet = new HashSet<String>(remainingItems); for (String str : remainingItems) { alternateSet.remove(str); // ... 递归操作 }
第一次循环remove(str)后,alternateSet已经丢失了一个元素,后续循环再执行remove(str)时,操作的是已经被修改过的集合,会导致递归传入的remainingItems不正确,最终生成的排列数量可能不对(虽然你说计数器是对的,但这只是巧合,测试更大的集合就会暴露问题)。
修复方法
把alternateSet的创建放到for循环内部,每次循环都基于原始的remainingItems创建新的副本:
for (String str : remainingItems) { Set<String> alternateSet = new HashSet<>(remainingItems); alternateSet.remove(str); // ... 递归操作 }
修改后的完整extendPermutation方法
public void extendPermutation(Set<String> remainingItems, Stack<String> permutationSoFar, List<List<String>> allPermutations){ if (remainingItems.isEmpty()) { // 存储当前栈的副本,避免后续pop修改已保存的排列 allPermutations.add(new ArrayList<>(permutationSoFar)); this.counter = counter + 1; return; // 提前返回,避免进入循环 } for (String str : remainingItems) { // 每次循环创建新的剩余元素集合副本 Set<String> alternateSet = new HashSet<>(remainingItems); alternateSet.remove(str); permutationSoFar.push(str); extendPermutation(alternateSet, permutationSoFar, allPermutations); permutationSoFar.pop(); } }
验证效果
修复后,findPermutations返回的列表里每个子列表都是独立的排列结果,printAll方法就能正常打印出所有排列了,计数器的统计也会保持正确。
内容的提问来源于stack exchange,提问作者pixtriestodocoding

