问题如下:
编写一个静态方法子集,该子集使用递归回溯来查找给定列表的每个可能的子列表。列表L的子列表包含0个或更多个L's元素。您的方法应接受字符串列表作为其参数,并打印可从该列表的元素创建的每个子列表,每行一个。例如,假设名为list的变量存储以下元素:
[Janet, Robert, Morgan, Char]
子集的调用(列表);会产生如下输出:
[Janet, Robert, Morgan, Char]
[Janet, Robert, Morgan]
[Janet, Robert, Char]
[Janet, Robert]
[Janet, Morgan, Char]
[Janet, Morgan]
[Janet, Char]
[Janet]
[Robert, Morgan, Char]
[Robert, Morgan]
[Robert, Char]
[Robert]
[Morgan, Char]
[Morgan]
[Char]
[]
我的部分解决方案要求使用递归回溯:
ListIterator<String> itr = choices.listIterator();
while (itr.hasNext()) {
String word = itr.next();
chosen.add(word);
itr.remove();
subsets(choices, chosen, alreadyPrinted);
chosen.remove(word);
itr.add(word);
}
但是我在包含itr.add(word)的行上得到了ConcurrentModificationException。为什么?我认为ListIterator的重点是避免这个问题吗?
编辑:我也试过像这样解决它:for (String word : choices) {
List<String> choicesCopy = choices;
chosen.add(word);
choicesCopy.remove(word);
subsets(choicesCopy, chosen, alreadyPrinted);
}
我仍然得到并发修改例外.... :( 这是怎么回事?根本没有对原始列表进行修改......
答案 0 :(得分:2)
不完全是,问题是(很可能)每次递归时都会创建ListIterator()
。每个List Iterator都试图修改相同的基础单词列表,从而触发异常。这是不允许的。
解决方案是每次递归时提供单词列表的副本。像这样,每个列表迭代器都可以在自己的个人列表中工作。
答案 1 :(得分:0)
ListIterator
。
ConcurrentModificationException
的原因是您在迭代它时通过添加和删除元素来修改基础列表。我相信你将不得不使用更原始的迭代技术,比如传统的for
循环,并自己跟踪迭代值。
从以上链接:
如果线程修改了集合 直接迭代 快速失败的集合 迭代器,迭代器会抛出这个 例外
Here是另一篇关于它的快速文章。
答案 2 :(得分:0)
在每次递归调用时创建新的迭代器,然后使用它删除/添加。 当你向上移动堆栈时,旧的迭代器会检测到变化并产生异常。
您应该重新考虑此代码。
答案 3 :(得分:0)
你的第二个解决方案有一个简单的错误。
List<String> choicesCopy = choices;
这不会创建列表的副本。您可以使用ArrayList.clone()或LinkedList.clone()或创建一个这样的新列表
List<String> choicesCopy = new LinkedList<String>(choices);