Двоичное дерево обхода порядка уровня с использованием двух очередей

#java #tree #binary-tree #tree-traversal

#java #дерево #двоичное дерево #обход дерева

Вопрос:

Проблема с Leetcode: https://leetcode.com/problems/binary-tree-level-order-traversal /

У меня есть две очереди, я очищаю свою первую очередь (q), добавляя элементы во вторую очередь (q2), таким образом, я могу получить уровни. Когда первая очередь пуста, я передаю ее в function, чтобы создать ArrayList этого уровня и добавить к моему результату значение, если q2 пуст, это означает, что ничего не было добавлено, поэтому мы можем выйти из цикла и вернуть функцию. Я должен вручную добавить первый узел. Проблема в том, что добавляется только средний уровень, а не остальные.

 /**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public List<List<Integer>> levelOrder(TreeNode root) {
        if(root == null) {
            return null;
        }
        
        List<List<Integer>> returnList = new ArrayList<>();
        Queue<TreeNode> q = new LinkedList<>();
        q.add(root);
        List<Integer> tempList = new ArrayList<>();
        tempList.add(root.val);
        returnList.add(tempList);
        
        while(true) {
            Queue<TreeNode> q2 = new LinkedList<>();
            while(!q.isEmpty()) {
                TreeNode node = q.remove();
           
                if(node.left != null) {
                    q2.add(node.left);
                }
                if(node.right != null) {
                    q2.add(node.right); 
                }
            }
            
            if(q2.isEmpty()) {
                break;
            }
  
            q = q2;
            addList(returnList, q2);
       
        }
        return returnList;
    }
    
    public static void addList(List<List<Integer>> returnList, Queue<TreeNode> q2) {
        List<Integer> tempList = new ArrayList<>();
        int size = q2.size();
        for(int i = 0; i < size; i  ) {
            int val = q2.remove().val;
            System.out.println(val);
            tempList.add(val);
        }
        returnList.add(tempList);
    }
}
  

Ответ №1:

Проблема связана с этой частью кода:

     q = q2;
    addList(returnList, q2);
  

Функция addList очистит данную очередь q2 , вызвав remove ее. Как q стало ссылкой на ту же очередь, вы очистили q , и поэтому следующая итерация внешнего цикла не попадет во внутренний цикл, а выйдет из внешнего цикла с помощью a break .

Чтобы этого не произошло, убедитесь, что remove вызовы не выполняются на q : make a copy:

     q = new LinkedList<>(q2);
    addList(returnList, q2);
  

или, в качестве альтернативы:

     q = q2;
    addList(returnList, new LinkedList<>(q2));