首页 > 代码库 > [LeetCode] Construct Binary Tree from String 从字符串创建二叉树

[LeetCode] Construct Binary Tree from String 从字符串创建二叉树

 

You need to construct a binary tree from a string consisting of parenthesis and integers.

The whole input represents a binary tree. It contains an integer followed by zero, one or two pairs of parenthesis. The integer represents the root‘s value and a pair of parenthesis contains a child binary tree with the same structure.

You always start to construct the left child node of the parent first if it exists.

Example:

Input: "4(2(3)(1))(6(5))"Output: return the tree root node representing the following tree:       4     /       2     6   / \   /   3   1 5   

 

Note:

  1. There will only be ‘(‘‘)‘‘-‘ and ‘0‘ ~ ‘9‘ in the input string.
  2. An empty tree is represented by "" instead of "()".

 

这道题让我们根据一个字符串来创建一个二叉树,其中结点与其左右子树是用括号隔开,每个括号中又是数字后面的跟括号的模式,这种模型就很有递归的感觉,所以我们当然可以使用递归来做。首先我们要做的是先找出根结点值,我们找第一个左括号的位置,如果找不到,说明当前字符串都是数字,直接转化为整型,然后新建结点返回即可。否则的话从当前位置开始遍历,因为当前位置是一个左括号,我们的目标是找到与之对应的右括号的位置,但是由于中间还会遇到左右括号,所以我们需要用一个变量cnt来记录左括号的个数,如果遇到左括号,cnt自增1,如果遇到右括号,cnt自减1,这样当某个时刻cnt为0的时候,我们就确定了一个完整的子树的位置,那么问题来了,这个子树到底是左子树还是右子树呢,我们需要一个辅助变量start,当最开始找到第一个左括号的位置时,将start赋值为该位置,那么当cnt为0时,如果start还是原来的位置,说明这个是左子树,我们对其调用递归函数,注意此时更新start的位置,这样就能区分左右子树了,参见代码如下:

 

解法一:

class Solution {public:    TreeNode* str2tree(string s) {        if (s.empty()) return NULL;        auto found = s.find(();        int val = (found == string::npos) ? stoi(s) : stoi(s.substr(0, found));        TreeNode *cur = new TreeNode(val);        if (found == string::npos) return cur;        int start = found, cnt = 0;        for (int i = start; i < s.size(); ++i) {            if (s[i] == () ++cnt;            else if (s[i] == )) --cnt;            if (cnt == 0 && start == found) {                cur->left = str2tree(s.substr(start + 1, i - start - 1));                start = i + 1;            } else if (cnt == 0) {                cur->right = str2tree(s.substr(start + 1, i - start - 1));            }        }        return cur;    }};

 

下面这种解法使用迭代来做的,借助栈stack来实现。遍历字符串s,用变量j记录当前位置i,然后看当前遍历到的字符是什么,如果遇到的是左括号,什么也不做继续遍历;如果遇到的是数字或者负号,那么我们将连续的数字都找出来,然后转为整型并新建结点,此时我们看stack中是否有结点,如果有的话,当前结点就是栈顶结点的子结点,如果栈顶结点没有左子结点,那么此结点就是其左子结点,反之则为其右子结点。之后要将此结点压入栈中。如果我们遍历到的是右括号,说明栈顶元素的子结点已经处理完了,将其移除栈,参见代码如下:

 

解法二:

class Solution {public:    TreeNode* str2tree(string s) {        if (s.empty()) return NULL;        stack<TreeNode*> st;        for (int i = 0; i < s.size(); ++i) {            int j = i;            if (s[i] == )) st.pop();            else if ((s[i] >= 0 && s[i] <= 9) || s[i] == -) {                while (i + 1 < s.size() && s[i + 1] >= 0 && s[i + 1] <= 9) ++i;                TreeNode *cur = new TreeNode(stoi(s.substr(j, i - j + 1)));                if (!st.empty()) {                    TreeNode *t = st.top();                    if (!t->left) t->left = cur;                    else t->right = cur;                }                st.push(cur);            }        }        return st.top();    }};

 

参考资料:

https://discuss.leetcode.com/topic/82605/java-stack-solution

https://discuss.leetcode.com/topic/82572/java-recursive-solution/2

 

LeetCode All in One 题目讲解汇总(持续更新中...)

[LeetCode] Construct Binary Tree from String 从字符串创建二叉树