1. 程式人生 > 實用技巧 >根據一棵樹的前序遍歷與中序遍歷構造二叉樹

根據一棵樹的前序遍歷與中序遍歷構造二叉樹

轉載自:https://leetcode-cn.com/problems/zhong-jian-er-cha-shu-lcof/solution/4chong-jie-fa-di-gui-zhan-dui-lie-by-sdwwld/

方法一:使用棧解決

如果使用棧來解決首先要搞懂一個知識點,就是前序遍歷挨著的兩個值比如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; }