原題鏈接: http://oj.leetcode.com/problems/binary-tree-postorder-traversal/
跟Binary
Tree Inorder Traversal以及Binary
Tree Preorder Traversal一樣,二叉樹的後序遍歷我們還是介紹三種方法,第一種是遞歸,第二種是迭代方法,第三種是用線索二叉樹。 遞歸還是那麼簡單,算法的時間復雜度是O(n), 而空間復雜度則是遞歸棧的大小,即O(logn)。代碼如下:
public ArrayList接下來是迭代的做法,本質就是用一個棧來模擬遞歸的過程,但是相比於Binary Tree Inorder Traversal和Binary Tree Preorder Traversal,後序遍歷的情況就復雜多了。我們需要維護當前遍歷的cur指針和前一個遍歷的pre指針來追溯當前的情況(注意這裡是遍歷的指針,並不是真正按後序訪問順序的結點)。具體分為幾種情況:postorderTraversal(TreeNode root) { ArrayList res = new ArrayList (); helper(root, res); return res; } private void helper(TreeNode root, ArrayList res) { if(root == null) return; helper(root.left,res); helper(root.right,res); res.add(root.val); }
public ArrayList最後介紹Morris遍歷方法,這個方法不需要為每個節點額外分配指針指向其前驅和後繼結點,而是利用葉子節點中的右空指針指向中序遍歷下的後繼節點就可以了,所以優勢在於不需要額外空間。不過同樣相比於Binary Tree Inorder Traversal和Binary Tree Preorder Traversal,後序遍歷的情況要復雜得多,因為後序遍歷中一直要等到孩子結點訪問完才能訪問自己,需要一些技巧來維護。postorderTraversal(TreeNode root) { ArrayList res = new ArrayList (); if(root == null) return res; LinkedList stack = new LinkedList(); stack.push(root); TreeNode pre = null; while(!stack.isEmpty()) { TreeNode cur = stack.peek(); if(pre==null || pre.left==cur || pre.right==cur) { if(cur.left!=null) { stack.push(cur.left); } else if(cur.right!=null) { stack.push(cur.right); } else { res.add(cur.val); stack.pop(); } } else if(cur.left==pre && cur.right!=null) { stack.push(cur.right); } else { res.add(cur.val); stack.pop(); } pre = cur; } return res; }
public ArrayList到目前為止,二叉樹的三種遍歷的三種方法都介紹過了,後序遍歷相比於前面兩種,還是要復雜一些,個人覺得面試中可能傾向於靠其他兩種遍歷,特別是像Morris遍歷方法,如果沒有准備過很難在面試中寫出這種方法的後序遍歷,主要還是要有概念,就是知道方法的存在性以及優劣的分析就可以了,不過遞歸法和迭代法還是需要掌握一下的。postorderTraversal(TreeNode root) { ArrayList res = new ArrayList (); TreeNode dummy = new TreeNode(0); dummy.left = root; TreeNode cur = dummy; TreeNode pre = null; while(cur!=null) { if (cur.left==null) { cur = cur.right; } else { pre = cur.left; while (pre.right!=null && pre.right!=cur) pre = pre.right; if (pre.right==null) { pre.right = cur; cur = cur.left; } else { reverse(cur.left, pre); TreeNode temp = pre; while (temp != cur.left) { res.add(temp.val); temp = temp.right; } res.add(temp.val); reverse(pre, cur.left); pre.right = null; cur = cur.right; } } } return res; } void reverse(TreeNode start, TreeNode end) { if (start == end) return; TreeNode pre = start; TreeNode cur = start.right; TreeNode next; while (pre != end) { next = cur.right; cur.right = pre; pre = cur; cur = next; } }