層次遍歷遞歸和非遞歸方法
如何遍歷一棵樹
有兩種通用的遍歷樹的策略:
-
深度優先搜索(DFS)
在這個策略中,我們采用深度作為優先級,以便從跟開始一直到達某個確定的葉子,然后再返回根到達另一個分支。
深度優先搜索策略又可以根據根節點、左孩子和右孩子的相對順序被細分為先序遍歷,中序遍歷和后序遍歷。
-
寬度優先搜索(BFS)
我們按照高度順序一層一層的訪問整棵樹,高層次的節點將會比低層次的節點先被訪問到。
下圖中的頂點按照訪問的順序編號,按照 1-2-3-4-5 的順序來比較不同的策略。
層次遍歷可以采用兩種方法遞歸和迭代:
方法1:遞歸
算法
最簡單的解法就是遞歸,首先確認樹非空,然后調用遞歸函數 helper(node, level),參數是當前節點和節點的層次。程序過程如下:
輸出列表稱為 levels,當前最高層數就是列表的長度 len(levels)。比較訪問節點所在的層次 level 和當前最高層次 len(levels) 的大小,如果前者更大就向 levels 添加一個空列表。
將當前節點插入到對應層的列表 levels[level] 中。
遞歸非空的孩子節點:helper(node.left / node.right, level + 1)
class Solution { List<List<Integer>> levels = new ArrayList<List<Integer>>(); public void helper(TreeNode node, int level) { // start the current level if (levels.size() == level) levels.add(new ArrayList<Integer>()); // fulfil the current level levels.get(level).add(node.val); // process child nodes for the next level if (node.left != null) helper(node.left, level + 1); if (node.right != null) helper(node.right, level + 1); } public List<List<Integer>> levelOrder(TreeNode root) { if (root == null) return levels; helper(root, 0); return levels; } }
復雜度分析
時間復雜度:O(N)O(N)O(N),因為每個節點恰好會被運算一次。
空間復雜度:O(N)O(N)O(N),保存輸出結果的數組包含 N 個節點的值。
方法2:迭代
算法
上面的遞歸方法也可以寫成迭代的形式。
我們將樹上頂點按照層次依次放入隊列結構中,隊列中元素滿足 FIFO(先進先出)的原則。在 Java 中可以使用 Queue 接口中的 LinkedList實現。
第 0 層只包含根節點 root ,算法實現如下:
-
初始化隊列只包含一個節點 root 和層次編號 0 : level = 0。
-
當隊列非空的時候:
在輸出結果 levels 中插入一個空列表,開始當前層的算法。
計算當前層有多少個元素:等於隊列的長度。
將這些元素從隊列中彈出,並加入 levels 當前層的空列表中。
將他們的孩子節點作為下一層壓入隊列中。
進入下一層 level++。
class Solution { public List<List<Integer>> levelOrder(TreeNode root) { List<List<Integer>> levels = new ArrayList<List<Integer>>(); if (root == null) return levels; Queue<TreeNode> queue = new LinkedList<TreeNode>(); queue.add(root); int level = 0; while ( !queue.isEmpty() ) { // start the current level levels.add(new ArrayList<Integer>()); // number of elements in the current level int level_length = queue.size(); for(int i = 0; i < level_length; ++i) { TreeNode node = queue.remove(); // fulfill the current level levels.get(level).add(node.val); // add child nodes of the current level // in the queue for the next level if (node.left != null) queue.add(node.left); if (node.right != null) queue.add(node.right); } // go to next level level++; } return levels; } }
復雜度分析
時間復雜度:O(N)O(N)O(N),因為每個節點恰好會被運算一次。
空間復雜度:O(N)O(N)O(N),保存輸出結果的數組包含 N 個節點的值。