1. 程式人生 > >Leetcode:驗證二叉樹的前序遍歷

Leetcode:驗證二叉樹的前序遍歷

序列化二叉樹的一種方法是使用前序遍歷。當我們遇到一個非空節點時,我們可以記錄下這個節點的值。如果它是一個空節點,我們可以使用一個標記值記錄,例如 #

     _9_
    /   \
   3     2
  / \   / \
 4   1  #  6
/ \ / \   / \
# # # #   # #

例如,上面的二叉樹可以被序列化為字串 "9,3,4,#,#,1,#,#,2,#,6,#,#",其中 # 代表一個空節點。

給定一串以逗號分隔的序列,驗證它是否是正確的二叉樹的前序序列化。編寫一個在不重構樹的條件下的可行演算法。

每個以逗號分隔的字元或為一個整數或為一個表示 null

 指標的 '#' 。

你可以認為輸入格式總是有效的,例如它永遠不會包含兩個連續的逗號,比如 "1,,3" 。

示例 1:

輸入: "9,3,4,#,#,1,#,#,2,#,6,#,#"
輸出: true

示例 2:

輸入: "1,#"
輸出: false

示例 3:

輸入: "9,#,#,1"
輸出: false

解題思路:

  1. 利用字串建立二叉樹,檢視最後是否有剩餘結點,或者中途失敗。
  2. 同樣的方法,不建立二叉樹,只計算中的出度。

建立二叉樹的方法有的資料結構的課本講到過,有兩種方法一種是迭代法,另一種是遞迴法。

主要介紹下度的計算。

首先要明白下面幾點。

字元一共有兩種,數字和‘#’

1.加入數字後整個樹的出度加1

2.加入'#'出度減1.

累加的過程中,一旦發現整個樹的出度小於0是,建立樹就失敗了。

C++程式碼

//方法1

class Solution {
public:
    struct TreeNode {
        string val;
        TreeNode *left;
        TreeNode *right;
        TreeNode(string x) : val(x), left(NULL), right(NULL) {}
    };
    bool isValidSerialization(string preorder) {
        int size = preorder.size(),i;
        for (i = 1; i <= size; i++) {
            if (preorder[i - 1] == ',') preorder[i - 1] = ' ';
        }
        stringstream ss;
        ss << preorder;
        
        string sgn;
        while (ss >> sgn) {
            data.push_back(sgn);
        }
        if (int(data.size()) == 1) return data.back() == "#";
         //判斷data的先序序列化
        return isValid();
    }
private:
    bool isValid() {
        int pos = 0;
        stack<TreeNode*> S;
        TreeNode* root=new TreeNode(""), *p = root;
        while (data[pos] != "#") {
            p->left = new TreeNode(data[pos++]);
            S.push(p->left);
            p = p->left;
        }
        while (!S.empty()) {
            p = S.top();
            if (!p->left) {
                if (pos >= int(data.size())) return false;
                p->left = new TreeNode(data[pos++]);
                if (pos >= int(data.size())) return false;
                p->right = new TreeNode(data[pos++]);
                p = p->right;
                if (p->val != "#") {
                    S.push(p);
                    while (data[pos] != "#") {
                        if (pos >= int(data.size())) return false;
                        p->left = new TreeNode(data[pos++]);
                        p = p->left;
                        S.push(p);
                    }
                }
            }
            else if(!p->right){
                if (pos >= int(data.size())) return false;
                p->right = new TreeNode(data[pos++]);
                if (p->right->val == "#") continue;
                else {
                    S.push(p->right);
                    p = p->right;
                    while (data[pos] != "#") {
                        if (pos >= int(data.size())) return false;
                        p->left = new TreeNode(data[pos++]);
                        p = p->left;
                        S.push(p);
                    }
                }
            }
            else S.pop();
        }
        return pos == int(data.size());
    }
vector<string> data;
};

//方法2

class Solution {
public:
    bool isValidSerialization(string preorder) {
        if (preorder.empty()) return true;
        int n = preorder.size();
        int s = 1;
        for (int i = 0; i<n; ++i) {
            if (preorder[i] == '#') --s, ++i;
            else {
                for (; i<n && preorder[i] != ','; ++i);
                if (s == 0) return false;
                ++s;
            }
            if (s<0) return false;
        }
        return s == 0;
    }
};