2017-03-29 3 views
0
public void dfsSearch (TreeNode root, List<String> curr, List<List<String>> res) { 
     curr.add(String.valueOf(root.val)); 
     // a leaf node has been reached 
     if (root.left == null && root.right == null) { 
      res.add(curr); 
      return; 
     } 
     if (root.left != null) { 
      List<String> temp = new ArrayList<>(curr); 
      dfsSearch(root.left, temp, res); 
     } 
     if (root.right != null) { 
      List<String> temp = new ArrayList<>(curr); 
      dfsSearch(root.right, temp, res); 
     } 
    } 

上記のコードは、バイナリツリーのルートから葉までのすべてのパスを見つけるためにdfsを使う方法です。私の質問は、再帰呼び出しの上の2行で、なぜ新しいリストをインスタンス化する必要があるのですか?この一時リスト(temp)を再帰呼び出しに渡すと、curr(関数の引数)を使用できないのはなぜですか?再帰呼び出しの前に新しいリストをインスタンス化するのはなぜですか?

+0

この質問を明確にするには、各再帰呼び出しの前に、なぜここで新しいリストtempを使用する必要があり、代わりにcurrを使用できないのでしょうか? –

+0

currが再帰的に変更されているためです。あなたがバイナリツリーの左側を見ているとします(これはDFSでやることです)。あなたは葉を打つので、currは最初の葉への道を持っています。再帰スタックからポップすると、同じcurrを使用すると、右に移動して右の子ノードを追加するため、currは間違って以前の再帰呼び出しのリーフを持ち、今すぐ正しい子を持ちます。 –

+0

私はそのリストに言及する価値があると思うリファレンスタイプです。これは、 'curr'リストをパラメータとして渡すと、呼び出されている新しいメソッドの新しいオブジェクトを作成しないことを意味します。呼び出し元のメソッドと同じオブジェクトです。そのため、 'res'リストの一時リストを作成せず、すべての再帰呼び出しで同じリストを変更する必要があります。 –

答えて

0

が、これは

 1 
    2 3 
    4 5 

のは、あなたがtempを使用していなかったとしましょう、あなたのバイナリツリー

で想像してみてください。次に、バイナリツリーの左側を再帰して、currが1,2、および4を追加することを意味します。リストは変更可能なので、それらの値は再帰呼び出しからポップしても再帰呼び出しに保存されます。したがって、currに4を加えた後、ノード2に戻り、右に移動して5を追加します。したがって、currには、1,2,4および1,2が必要です、5。

+0

Freddy Hdzと同じように、List in javaは参照型ですが、新しいリストを作成しないと、呼び出されたメソッドと呼び出すメソッドに同じcurrを使用することになります。 –

0

dfsSearchメソッドが再帰的に呼び出されたときに、currの同時変更を防止するためのコピーです。最初の行curr.add(String.valueOf(root.val));currコレクションを変更しますが、コレクションを変更しながらコレクションをループすることはできません。

+1

このメソッドが同時に呼び出されていることをどのように知っていますか? –

+0

再帰自体が並行処理のソースです。 'dfsSearch'への外部/親呼び出しは実行中ですが、まだそのブロックを終了していませんが、' dfsSearch'の内部/子呼び出しが実行され、bam! – rmirabelle

0

同時変更がその理由の1つです。さらに、このアルゴリズムは、List of Lists結果のルートからリーフまでの "すべてのパス"を収集します。再帰的な方法で各レベルで新しいリストを作成しなかった場合は、再帰バブルアップ後に大きな混乱を招くリストが1つ作成されます(ルートからリーフまでのすべてのパスが、自分のリスト)。

関連する問題