【Leetcode】536. Construct Binary Tree from String

题目地址:

https://leetcode.com/problems/construct-binary-tree-from-string/

给定一个长 n n n字符串 s s s,只含左括号、右括号、负号和 0 ∼ 9 0\sim 9 09的数字。要求将其构造为一棵二叉树。构造规则是这样的,字符串要么是空串(则返回空树),要么以一个数开头(可正可负),后面接着两块括号,第一个括号内是左子树对应的字符串,第二个是右子树对应的字符串(当然也可能只有左子树没有右子树,此时只接一块括号)。返回树根。

法1:递归。设一个函数 f f f可以以当前走到的下标 u u u s s s作为参数,其能保证 s [ u ] s[u] s[u]要么是数字(也可能是 − - ),要么 u u u走到末尾;其功能是,构造以 s [ u ] s[u] s[u]数字的二叉树,并且将 u u u移到该二叉树的子串的后一个位置。那么 f ( 0 , s ) f(0,s) f(0,s)即为所求。考虑如何实现 f f f。如果 u u u已经指向末尾,则无法构造树,返回null;否则先截取出数字,并让 u u u越过该数字。现在 u u u如果没有指向 ( ( ((或者 u u u指向了末尾),就说明这个 s [ u ] s[u] s[u]的子树只有一个节点,此时 u u u是满足要求的,可以直接返回树根;如果 u u u指向了左括号,则递归求解左子树,如果接下来 u u u还是指向了左括号,说明右子树存在,递归求解右子树。最后返回树根。代码如下:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left),
 * right(right) {}
 * };
 */
class Solution {
 public:
  TreeNode* str2tree(string s) {
    int idx = 0;
    return dfs(idx, s);
  }

  TreeNode* dfs(int& idx, string& s) {
    if (idx == s.size()) return nullptr;
    int sign = 1;
    if (s[idx] == '-') sign = -1, idx++;
    int i = idx;
    while (idx < s.size() && isdigit(s[idx])) idx++;
    auto root = new TreeNode(sign * stoi(s.substr(i, idx - i)));
    if (idx < s.size() && s[idx] == '(') {
      // 略过左括号,然后递归求解左子树,接着略过右括号
      idx++;
      root->left = dfs(idx, s);
      idx++;
    }

    if (idx < s.size() && s[idx] == '(') {
      // 与上同
      idx++;
      root->right = dfs(idx, s);
      idx++;
    }
    return root;
  }
};

时间复杂度 O ( n ) O(n) O(n),空间 O ( h ) O(h) O(h)

法2:栈。遇到数字或负号,则先解析出数字,然后new出节点,如果栈空,则直接将节点入栈,否则看一下栈顶的左孩子是否空,如果空,则append到左边,否则append到右边,接着将new出的节点入栈;如果遇到右括号,则pop栈顶;遇到左括号直接忽略。代码如下:

class Solution {
 public:
  TreeNode* str2tree(string s) {
    stack<TreeNode*> stk;
    for (int i = 0; i < s.size(); i++) {
      if (s[i] == '-' || isdigit(s[i])) {
        // 截取出数字
        int sign = 1;
        if (s[i] == '-') sign = -1, i++;
        int j = i;
        while (i < s.size() && isdigit(s[i])) i++;
        auto node = new TreeNode(sign * stoi(s.substr(j, i - j)));
        // i要挪到数字的最后一位,以便循环i++的时候不错误跳过字符
        i--;
        // 优先append到栈顶左儿子,如果栈顶已经有了左儿子,则append到右儿子
        if (stk.size()) {
          if (!stk.top()->left)
            stk.top()->left = node;
          else
            stk.top()->right = node;
        }
        // 存左链
        stk.push(node);
      } else if (s[i] == ')')
        stk.pop();
    }
	return stk.size() ? stk.top() : nullptr;
  }
};

时空复杂度一样。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值