1. 程式人生 > >LeetCode 演算法學習(11)

LeetCode 演算法學習(11)

題目描述

Construct Binary Tree from Preorder and Inorder Traversal
Given preorder and inorder traversal of a tree, construct the binary tree.

Note:
You may assume that duplicates do not exist in the tree.

題目大意

根據給出的先序遍歷和中序遍歷順序,畫出他們所確定的二叉樹。

思路分析

先序遍歷:NLR,中序遍歷:LNR。根據這個特點,可以根據先序遍歷的次序確定根結點,再由根節點在中序遍歷中的位置確定它的位置,或者說將中序遍歷分成左子樹部分和右子樹部分。
這裡我採用了利用棧實現非遞迴的演算法,關鍵在於如何處理結點在中序遍歷中的位置和二叉樹中的位置之間的關係。
利用棧,若該結點的位置在中序遍歷中處於棧頂結點的左側(<棧頂結點的位置),那麼它就是棧頂結點的左結點,將其連結起來併入棧;當該結點的位置在中序遍歷中處於棧頂結點的右側,說明它是棧頂結點或其祖先結點的右結點,關鍵就在於找到這個祖先結點。觀察得知,這個祖先結點應該是棧中最後一個位於該結點左側的結點,所以只要一直出棧來,就可以找到這個祖先結點。

關鍵程式碼

    int findX(vector<int> v, int x) {
        int n = v.size();
        for (int i = 0; i < n; i++) {
            if (v[i] == x) return i;
        }
        return -1;
    }
    TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
        int n = preorder.
size(); if (n == 0) return NULL; TreeNode *root = new TreeNode(preorder[0]); stack<TreeNode*> stackTN; stack<int> stackPos; stackTN.push(root); stackPos.push(findX(inorder, preorder[0])); for (int i = 1; i < n; i++) { int
temp = findX(inorder, preorder[i]); TreeNode *tempNode = new TreeNode(preorder[i]); TreeNode *tobe; if (temp < stackPos.top()) { stackTN.top()->left = tempNode; stackTN.push(tempNode); stackPos.push(temp); } else { while (!stackPos.empty() && temp > stackPos.top()) { // 尋找祖先結點 tobe = stackTN.top(); stackPos.pop(); stackTN.pop(); } tobe->right = tempNode; stackTN.push(tempNode); stackPos.push(temp); } } return root; }

總結

這是二叉樹的經典操作,與此同時,還順便複習了利用棧實現非遞迴的演算法。