1

問題は次のとおりです。

再帰的なバックトラッキングを使用して、指定されたリストの可能なすべてのサブリストを見つける静的メソッド サブセットを記述します。リスト L のサブリストには、L の要素が 0 個以上含まれています。メソッドは、文字列のリストをパラメーターとして受け入れ、そのリストの要素から作成できるすべてのサブリストを 1 行に 1 つずつ出力する必要があります。たとえば、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);
      } 

私はまだconcurrentmodificationexceptionを取得しています.... : (これはどうやって起こっているのですか?元のリストの変更はまったくありません.

4

4 に答える 4

2

正確ではありませんが、問題は (ほとんどの場合)ListIterator()再帰的になるたびに作成することです。各 List Iterator は、同じ基礎となる単語のリストを変更しようとしているため、例外がトリガーされます。これは許可されていません。

解決策は、再帰的になるたびに単語のリストのコピーを提供することです。このように、各リスト反復子は独自の個人用リストで機能します。

于 2011-05-27T00:59:44.727 に答える
0

2番目の解決策には、単純な間違いがあります。

List<String> choicesCopy = choices;

これはリストのコピーを作成しません。ArrayList.clone()またはLinkedList.clone()を使用するか、次のような新しいリストを作成できます。

List<String> choicesCopy = new LinkedList<String>(choices);
于 2011-05-27T02:35:16.817 に答える
0

編集: OP が . を使用していたことを見逃しましたListIterator

の理由は、ConcurrentModificationException反復処理中に要素を追加したり削除したりして、基になるリストを変更しているためです。従来のループのような、より原始的な反復手法を使用しfor、反復値を自分で追跡する必要があると思います。

上記のリンクから:

フェイルファスト反復子を使用してコレクションを反復処理しているときに、スレッドがコレクションを直接変更すると、反復子はこの例外をスローします。

これに関する別の簡単な記事を次に示します。

于 2011-05-27T01:01:19.787 に答える
0

再帰呼び出しごとに新しいイテレータを作成し、それを使用して削除/追加します。スタックを上ると、古いイテレータが変更を検出して例外を生成します。

このコードを再考する必要があります。

于 2011-05-27T01:02:58.243 に答える