根據一棵樹的前序遍歷與中序遍歷構造二叉樹
阿新 • • 發佈:2021-01-07
方法一:使用棧解決
如果使用棧來解決首先要搞懂一個知識點,就是前序遍歷挨著的兩個值比如m和n,他們會有下面兩種情況之一的關係。
1,n是m左子樹節點的值。
2,n是m右子樹節點的值或者是m某個祖先節點的右節點的值。
對於第一個知識點我們很容易理解,如果m的左子樹不為空,那麼n就是m左子樹節點的值。
對於第二個問題,如果一個結點沒有左子樹只有右子樹,那麼n就是m右子樹節點的值,如果一個結點既沒有左子樹也沒有右子樹,那麼n就是m某個祖先節點的右節點,我們只要找到這個祖先節點就好辦了。
搞懂了這點,程式碼就很容易寫了,下面看下完整程式碼
public TreeNode buildTree(int[] preorder, int[] inorder) { if (preorder.length == 0) return null; Stack<TreeNode> s = new Stack<>(); //前序的第一個其實就是根節點 TreeNode root = new TreeNode(preorder[0]); TreeNode cur = root; for (int i = 1, j = 0; i < preorder.length; i++) {//第一種情況 if (cur.val != inorder[j]) { cur.left = new TreeNode(preorder[i]); s.push(cur); cur = cur.left; } else { //第二種情況 j++; //找到合適的cur,然後確定他的右節點 while (!s.empty() && s.peek().val == inorder[j]) { cur= s.pop(); j++; } //給cur新增右節點 cur = cur.right = new TreeNode(preorder[i]); } } return root; }
方法二:遞迴法
class Solution { private int in = 0; private int pre = 0; private int[] preorder; private int[] inorder; public TreeNode buildTree(int[] preorder, int[] inorder) { this.preorder = preorder; this.inorder = inorder; return build(Integer.MIN_VALUE); } private TreeNode build(int stop) { if (pre >= preorder.length) return null; if (inorder[in] == stop) { in++; return null; } TreeNode node = new TreeNode(preorder[pre++]); node.left = build(node.val); //左子樹 當中序遍歷下一節點與前序遍歷相同時,到達葉節點 node.right = build(stop); //右子樹 當中序遍歷下一節點為當前節點的根節點時,到達葉節點 return node; }classSolution{ privateintin=0; privateintpre=0; privateint[]preorder; privateint[]inorder;
publicTreeNodebuildTree(int[]preorder,int[]inorder){ this.preorder=preorder; this.inorder=inorder; returnbuild(Integer.MIN_VALUE); }
privateTreeNodebuild(intstop){ if(pre>=preorder.length) returnnull; if(inorder[in]==stop){ in++; returnnull; }
TreeNodenode=newTreeNode(preorder[pre++]); node.left=build(node.val);//左子樹當中序遍歷下一節點與前序遍歷相同時,到達葉節點 node.right=build(stop);//右子樹當中序遍歷下一節點為當前節點的根節點時,到達葉節點 returnnode; }