leetcode1028. 從先序遍歷還原二叉樹/先序遍歷

題目:leetcode1028. 從先序遍歷還原二叉樹

我們從二叉樹的根節點 root 開始進行深度優先搜索。

在遍歷中的每個節點處,我們輸出 D 條短劃線(其中 D 是該節點的深度),然後輸出該節點的值。(如果節點的深度爲 D,則其直接子節點的深度爲 D + 1。根節點的深度爲 0)。

如果節點只有一個子節點,那麼保證該子節點爲左子節點。

給出遍歷輸出 S,還原樹並返回其根節點 root。

示例 1:

在這裏插入圖片描述

輸入:“1-2–3--4-5–6--7”
輸出:[1,2,5,3,4,6,7]


示例 2:

在這裏插入圖片描述

輸入:“1-2–3—4-5–6—7”
輸出:[1,2,5,3,null,6,null,4,null,7]


示例 3:
在這裏插入圖片描述

輸入:“1-401–349—90–88”
輸出:[1,401,null,349,88,90]

提示:

  • 原始樹中的節點數介於 1 和 1000 之間。
  • 每個節點的值介於 1 和 10 ^ 9 之間。

來源:力扣(LeetCode)
鏈接:https://leetcode-cn.com/problems/recover-a-tree-from-preorder-traversal
著作權歸領釦網絡所有。商業轉載請聯繫官方授權,非商業轉載請註明出處。

基本思想1:先序遍歷非遞歸形式

  • 先將字符串分割好,按照節點的值和節點的深度進行分割
  • 先序遍歷非遞歸形式遍歷二叉樹,藉助棧保存節點和節點的深度
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    TreeNode* recoverFromPreorder(string S) {
        if(S.length() == NULL)
            return NULL;
        //分隔字符串
        int j = 0, lev = 0, num = 0;
        vector<int> nums;
        vector<int> level;
        while(j < S.length()){
            lev = 0;
            while(j < S.length() && S[j] == '-'){
                ++lev;
                ++j;
            }
            level.push_back(lev);
            
            num = 0;
            while(j < S.length() && S[j] != '-'){
                num = num * 10 + S[j] - '0';
                ++j;
            }
            nums.push_back(num);            
        }
        
        //構造二叉樹
        TreeNode * root, *p;
        p = new TreeNode(nums[0]);
        root = p;
        j = 1;
        stack<TreeNode*> st;
        stack<int> stl;//保存節點的深度
        st.push(root);
        stl.push(0);
        int l;
        while(j < nums.size()){
            while(j < nums.size() && level[j] > level[j - 1]){                
                p->left = new TreeNode(nums[j]);
                p = p->left;
                st.push(p);
                stl.push(level[j]);
                ++j;
            }
            l = stl.top();            
            st.pop();
            stl.pop();
            if(j < nums.size() && level[j] == l){
                p = st.top();
                p->right = new TreeNode(nums[j]);
                p = p->right;
                st.push(p);
                stl.push(level[j]);
                ++j;
            }
            
            
        }
        return root;
    }
};

基本思想2:先序遍歷遞歸形式

遞歸形式的關鍵是:如何劃分左右子樹。
注意: 題目中指名如果只有一個子節點,那麼這個節點是左子節點
劃分左右子樹的方法:當前節點的下一個節點(如果存在)一定是當前節點的左子節點,尋找當前與當前的左字節點相同深度的節點就是右子樹的先序遍歷的第一個節點

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
private:
    vector<int> nums;
    vector<int> level;
public:
    TreeNode* recoverFromPreorder(string S) {
        if(S.length() == NULL)
            return NULL;
        //分隔字符串
        int j = 0, lev = 0, num = 0;
        
        while(j < S.length()){
            lev = 0;
            while(j < S.length() && S[j] == '-'){
                ++lev;
                ++j;
            }
            level.push_back(lev);
            
            num = 0;
            while(j < S.length() && S[j] != '-'){
                num = num * 10 + S[j] - '0';
                ++j;
            }
            nums.push_back(num);            
        }
        
        return create(0, nums.size() - 1);
    }
    TreeNode* create(int l, int r){
        if(l > r)
            return NULL;
        TreeNode* root = new TreeNode(nums[l]);
        if(l + 1 <= r){
            int i = l + 2;
            while(i <= r && level[i] != level[l + 1]){
                ++i;
            }
            root->left = create(l + 1, i - 1);
            root->right = create(i, r);
        }
        
        
        return root;
    }
};
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章