leetcode 1028. 从先序遍历还原二叉树

我们从二叉树的根节点 root 开始进行深度优先搜索。

在遍历中的每个节点处,我们输出 D 条短划线(其中 D 是该节点的深度),然后输出该节点的值。(如果节点的深度为 D,则其直接子节点的深度为 D + 1。根节点的深度为 0)。

如果节点只有一个子节点,那么保证该子节点为左子节点。

给出遍历输出 S,还原树并返回其根节点 root。 

 

题解:

1.字符串还原二叉树

2.输入中数字前的划线D 条短划线表示节点深度为D

3.根节点的深度为 0

4.节点只有一个子节点,该子节点为左子节点

 

示例 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 之间

 

解题思路:

  • 由于规定是先序遍历还原二叉树,先序遍历先根节点,不断遍历左子节点,再遍历右子节点

  • 分开几记录节点深度和节点值,节点值通过字符数字转换过去

  • 使用一个临时容器存放生成的节点

  • 如果节点深度小于容器中建成的树节点,则把工作指针回退到节点深度层上,对容器不断pop,回退到对应层,此时工作指针在容器最后一个节点上

  • 扩展子节点,先扩展左子节点(保证节点只有一个子节点,该子节点为左子节点),如果存在左子节点再扩展右子节点

C/C++题解:

/** * 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) {

        vector<TreeNode*> buffer;

        int idx=0; //遍历指针

        int slen=S.length();

        TreeNode* head=new TreeNode(0);

        TreeNode* nd=head;

        while(idx<slen){

            int lev=0;

            int val=0;

            while(idx<slen && S[idx]=='-'){

                ++lev;//数字前‘-’个数表示节点树深度

                ++idx;//跳过‘-’字符

            }//根据输入,如果是数字字符,则是节点值;连续数字字符是一个数

            while(idx<slen && S[idx]>='0' && S[idx]<='9'){

                val*=10; //计算出连续数字字符表示的数值

                val+=S[idx]-'0';

                ++idx;

            }//如果输入的树深比当前记录的节点数少,退回到树深为lev时的节点

            while(lev<buffer.size())buffer.pop_back();

            if(!buffer.empty())nd=buffer.back();//指针回到lev层

            if(nd->left==nullptr){//左节点为空

                nd->left=new TreeNode(val);//为其生成左子节点

                nd=nd->left; }//并走到左子节点位置

            else {//左子不空,有节点,生成右子节点

                nd->right=new TreeNode(val);

                nd=nd->right;//走到右子节点位置

            }//buffer容器存放建立过的树节点

            buffer.push_back(nd); }

        return head->left; }};//树从head-left开始,head头指针

Debug结果:

Java题解:

/** * Definition for a binary tree node.

 * public class TreeNode {

 *     int val;

 *     TreeNode left;

 *     TreeNode right;

 *     TreeNode(int x) { val = x; }* } */

class Solution {

    public TreeNode recoverFromPreorder(String S) {

        Stack<TreeNode> buffer=new Stack<TreeNode>();

        int idx=0; //遍历指针

        int slen=S.length();

        TreeNode head=new TreeNode(0);

        TreeNode nd=head;

        while(idx<slen){

            int lev=0;

            int val=0;

            while(idx<slen && S.charAt(idx)=='-'){

                ++lev;//数字前‘-’个数表示节点树深度

                ++idx;//跳过‘-’字符

            }//根据输入,如果是数字字符,则是节点值;连续数字字符是一个数

            while(idx<slen && S.charAt(idx)>='0' && S.charAt(idx)<='9'){

                val*=10; //计算出连续数字字符表示的数值

                val+=S.charAt(idx)-'0';

                ++idx;}//如果输入的树深比当前记录的节点数少,退回到树深为lev时的节点

            while(lev<buffer.size())buffer.pop();

            if(buffer.empty()==false) nd=buffer.peek();//指针回到lev层

            if(nd.left==null){//左节点为空

                nd.left=new TreeNode(val);//为其生成左子节点

                nd=nd.left; }//并走到左子节点位置

            else {//左子不空,有节点,生成右子节点

                nd.right=new TreeNode(val);

                nd=nd.right;//走到右子节点位置

            }//buffer容器存放建立过的树节点

            buffer.push(nd);}

        return head.left;}}//树从head-left开始,head头指针

Debug结果:

Python题解:

# Definition for a binary tree node.

# class TreeNode(object):

#     def __init__(self, x):

#         self.val = x

#         self.left = None

#         self.right = None

class Solution(object):

    def recoverFromPreorder(self, S):

        """:type S: str:rtype: TreeNode"""

        buf, idx, slen, head= [], 0, len(S), TreeNode(0)

        nd = head

        while idx<slen:

            lev, val= 0, 0

            while idx<slen and S[idx]=='-':

                lev += 1 #数字前‘-’个数表示节点树深度

                idx += 1 #/跳过‘-’字符

            #根据输入,如果是数字字符,则是节点值;连续数字字符是一个数

            while idx<slen and S[idx]>='0' and S[idx]<='9':

                val*=10 #计算出连续数字字符表示的数值

                val+=int(S[idx])

                idx += 1

            #如果输入的树深比当前记录的节点数少,退回到树深为lev时的节点

            while lev<len(buf):

                buf.pop()

            if buf:

                nd=buf[-1]#指针回到lev层

            if not nd.left:#左节点为空

                nd.left=TreeNode(val) #为其生成左子节点

                nd=nd.left #并走到左子节点位置

            else: #左子不空,有节点,生成右子节点

                nd.right=TreeNode(val)

                nd=nd.right#走到右子节点位置

            #buffer容器存放建立过的树节点

            buf.append(nd)

        return head.left#树从head-left开始,head头指针

Debug结果:

更多题解移步公众号免费获取

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
对称二叉树先序遍历是从根节点开始,先访问根节点,然后按照先左后右的顺序递归遍历左子和右子。这里引用的方法有三种思路实现先序遍历,其中思路1是最基本的实现方式,通过递归的方式遍历两次来判断是否对称。思路1的方法会导致整体上遍历了这棵两次,但实际上只需要比较到两个遍历节点相遇时即可停止,因为后续的比较结果和前面是完全一致的。所以,对于给定的对称二叉树先序遍历只需要比较到两个遍历节点相遇时即可停止。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [leetcode:Leetcode的解决方案,用JAVA编写](https://download.csdn.net/download/weixin_42121412/19697315)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* *3* [[] 101. 对称二叉树(前序遍历 + 方法优化)](https://blog.csdn.net/m0_38142029/article/details/108089313)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值