每日打卡:从先序遍历还原二叉树

打卡: 从先序遍历还原二叉树

心情

《隐秘的角落》电视剧拍得太真实了,每个人都背负着枷锁走在这个世界上。有些时候看着自己的内心,就像是看着一个不相干的人在做着另一个世界的事情。

读题

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

描述:
我们从二叉树的根节点 root 开始进行深度优先搜索。
在遍历中的每个节点处,我们输出 D 条短划线(其中 D 是该节点的深度),然后输出该节点的值。(如果节点的深度为 D,则其直接子节点的深度为 D + 1。根节点的深度为 0)。
如果节点只有一个子节点,那么保证该子节点为左子节点。
给出遍历输出 S,还原树并返回其根节点 root。

测试用例:
输入:“1-2–3--4-5–6--7”
输出:[1,2,5,3,4,6,7]
输入:“1-2–3—4-5–6—7”
输出:[1,2,5,3,null,6,null,4,null,7]
输入:“1-401–349—90–88”
输出:[1,401,null,349,88,90]

提示:
原始树中的节点数介于 1 和 1000 之间。
每个节点的值介于 1 和 10 ^ 9 之间。

先序遍历,二叉树,好熟悉~

思路

1:递归吧

实现

class Solution {
    public TreeNode recoverFromPreorder(String S) {
        TreeNode node = null;
        if (S != null && S.length() > 0) {
            String num = getNumber(S,"-");
            node = new TreeNode(Integer.valueOf(num));
            parseNode(node, S.substring(num.length()), "-");
        }
        return node;
    }

    /**
     * 字符串转换为树
     * @param node 当前节点
     * @param str  左侧树
     * @param trim 分割的字符串
     * @return
     */
    public String parseNode(TreeNode node, String str, String trim) {
        if (str.length() > 0) {
            String resultStr = trimStr(str, trim);
            //strs[0]必然为空,不为空也不需要处理
            //左侧树
            if (str.length() - resultStr.length() == trim.length()) {
                String num = getNumber(resultStr,"-");
                node.left = new TreeNode(Integer.valueOf(num));
                if (resultStr.length() > num.length()) {
                    str = parseNode(node.left, resultStr.substring(num.length()), trim + "-");
                }else{
                    str = resultStr;
                }
            }
            //右侧树
            resultStr = trimStr(str, trim);
            if (str.length() - resultStr.length() == trim.length()) {
                String num = getNumber(resultStr,"-");
                node.right = new TreeNode(Integer.valueOf(num));
                if (resultStr.length() > num.length()) {
                    str = parseNode(node.right, resultStr.substring(num.length()), trim + "-");
                }else{
                    str = resultStr;
                }
            }
        }
        return str;
    }

    /**
     * 移除字符串前面的指定字符串
     * @param str
     * @param prefix
     * @return
     */
    public String trimStr(String str, String prefix) {
        if (str.length() > 0 && str.startsWith(prefix)) {
            return trimStr(str.substring(prefix.length()), prefix);
        } else {
            return str;
        }
    }

    /**
     * 获取字符串最前面的数值
     * @param str
     * @param prefix
     * @return
     */
    public String getNumber(String str, String prefix) {
        if(str.indexOf(prefix)!=-1){
            str = str.substring(0,str.indexOf(prefix));
        }
        return str;
    }
}

还是比较清晰的思路,依次处理左节点再处理右节点。

提交

在这里插入图片描述
本想着用-分割子集,然后递归分割就能实现结果。结果卡在了第一步,用-分割子集要循环太多次……

标答

class Solution {
    public TreeNode recoverFromPreorder(String S) {
        // 存储当前节点的路径
        Deque<TreeNode> path = new LinkedList<TreeNode>();
        // 存储字符串中的位置
        int pos = 0;
        while (pos < S.length()) {
            // 获取当前层数
            int level = 0;
            while (S.charAt(pos) == '-') {
                ++level;
                ++pos;
            }
            // 获取节点值
            int value = 0;
            while (pos < S.length() && Character.isDigit(S.charAt(pos))) {
                value = value * 10 + (S.charAt(pos) - '0');
                ++pos;
            }
            // 构造当前节点
            TreeNode node = new TreeNode(value);
            if (level == path.size()) {
                //如果当前节点的深度==当前路径长度(前一个节点是当前节点的父节点)
                if (!path.isEmpty()) {
                    //如果不是第一个节点,前一个节点的左子节点为当前节点
                    path.peek().left = node;
                }
            }else {
                //如果当前节点的深度!=当前路径长度(前一个节点不是当前节点的父节点)
                while (level != path.size()) {
                    //通过queue弹出其他子节点,找到当前节点的父节点
                    path.pop();
                }
                // 找到父节点,因为此时左子节点已确定,所以赋值给右子节点
                path.peek().right = node;
            }
            // 放入queue中
            path.push(node);
        }
        // 全部弹出,只剩根节点
        while (path.size() > 1) {
            path.pop();
        }
        // 返回根
        return path.peek();
    }
}

官方题解

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值