重建二叉樹

1.題目

輸入一棵二叉樹前序遍歷和中序遍歷的結果,請重建該二叉樹。c++

注意:數組

  • 二叉樹中每一個節點的值都互不相同;
  • 輸入的前序遍歷和中序遍歷必定合法;

樣例數據結構

給定:
前序遍歷是:[3, 9, 20, 15, 7]
中序遍歷是:[9, 3, 15, 20, 7]

返回:[3, 9, 20, null, null, 15, 7, null, null, null, null]
返回的二叉樹以下所示:
    3
   / \
  9  20
    /  \
   15   7

這是題目地址,有興趣的能夠作一下。ui

2.時間複雜度爲O(nlogn)的解法

這個是本身作的,準確來講算是實踐了一下本身上數據結構課學到的知識吧。code

2.1 思路

若是前序序列不爲空,那麼第一個數必定是樹的根。咱們再從中序序列找到這個數所在的位置,左半部分就是根的左子樹,右半部分就是根的右子樹,咱們能夠把左子樹再看成一棵樹,適當縮小先序序列的範圍,第一個數就是這個左子樹的根,而後再在中序序列去尋找這個數,繼續劃分,依此類推,當序列只剩下一個數時,表明咱們找到了葉子節點,就不須要再繼續劃分了。遞歸

道理很簡單,可是操做起來出了點問題,仍是邊界問題,要親自實現一遍才知道本身哪裏有問題。get

本身的代碼也蠻複雜的,沒有用一些數記錄下標,直接將序列縮小進行遞歸,若是是利用下標值,能夠不須要這麼複雜。(此處就不修改代碼了)io

2.2 代碼

struct TreeNode {
    int val;
    TreeNode* left;
    TreeNode* right;
    TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};

void insertToTree(TreeNode* T, vector<int> preorder, vector<int> inorder) {
    T->val = preorder[0];
    //當此時數組中只有一個數時,表示當前節點無左右孩子,爲樹葉
    if (inorder.size() == 1)
        return;
    int i = 0;
    //尋找該數在中序數組中的位置,左半部分爲其左子樹,右半部分爲其右子樹。
    for (; i < inorder.size(); i++) {
        if (inorder[i] == T->val)
            break;
    }
    //此時位於中序數組第一位,代表無左孩子
    if (i == 0) {
        T->left = NULL;
        T->right = new TreeNode(0);
        insertToTree(T->right, vector<int>(preorder.begin() + i + 1, preorder.end()), vector<int>(inorder.begin() + i + 1, inorder.end()));
    }
    //位於中序數組最後一位,代表無右孩子
    else if (i == inorder.size() - 1) {
        T->right = NULL;
        T->left = new TreeNode(0);
        insertToTree(T->left, vector<int>(preorder.begin() + 1, preorder.begin() + i + 1), vector<int>(inorder.begin(), inorder.begin() + i));
    }
    //有左右孩子
    else {
        T->right = new TreeNode(0);
        T->left = new TreeNode(0);
        insertToTree(T->left, vector<int>(preorder.begin() + 1, preorder.begin() + i + 1), vector<int>(inorder.begin(), inorder.begin() + i));
        insertToTree(T->right, vector<int>(preorder.begin() + i + 1, preorder.end()), vector<int>(inorder.begin() + i + 1, inorder.end()));
    }
}

TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
    //若是是空序列,返回空樹
    if (inorder.size() == 0) return NULL;
    TreeNode* T = new TreeNode(0);
    insertToTree(T, preorder, inorder);
    return T;
}

3.時間複雜度爲O(n)的解法

這是題解,仍是學的知識沒用上,忘記了散列表這麼好用的東西。class

大佬的題解的原地址二叉樹

3.1 思路

思路和我本身想的是基本同樣的,只不過大佬在中序序列找數的這個過程當中用的是散列表(學了一直沒用過,致使如今都不會用)

3.2 代碼

unordered_map<int,int> pos;

    TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
        int n = preorder.size();
        for (int i = 0; i < n; i ++ )
            pos[inorder[i]] = i;
        return dfs(preorder, inorder, 0, n - 1, 0, n - 1);
    }

    TreeNode* dfs(vector<int>&pre, vector<int>&in, int pl, int pr, int il, int ir)
    {
        if (pl > pr) return NULL;
        int k = pos[pre[pl]] - il;
        TreeNode* root = new TreeNode(pre[pl]);
        root->left = dfs(pre, in, pl + 1, pl + k, il, il + k - 1);
        root->right = dfs(pre, in, pl + k + 1, pr, il + k + 1, ir);
        return root;
    }

做者:yxc
連接:https://www.acwing.com/solution/content/706/
來源:AcWing
著做權歸做者全部。商業轉載請聯繫做者得到受權,非商業轉載請註明出處。
相關文章
相關標籤/搜索