leetcode--从先序遍历还原二叉树

leetcode地址:从先序遍历还原二叉树
我们从二叉树的根节点 root 开始进行深度优先搜索。

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

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

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

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

实现思路

根据给定的深度优先搜索遍历输出字符串 S 还原出原始的二叉树。深度优先搜索的遍历顺序是前序遍历(即根节点->左子树->右子树),并且每个节点的深度由前面的短划线数决定。
解析字符串
首先解析字符串 S,找到每个节点的值和其深度。
用两个指针遍历字符串,一个用来确定深度,另一个用来读取节点的值。
构建树
用一个栈来辅助构建树。栈中的元素按深度递增顺序保存正在处理的节点。
遍历每个节点,根据深度确定其父节点,然后将其添加到树中。
如果当前节点的深度小于或等于栈顶节点的深度,弹出栈顶节点直到栈顶节点的深度小于当前节点的深度。
将当前节点加入到其父节点的左或右子树中,并将当前节点压入栈中。

代码详解

# 定义二叉树节点类
class TreeNode:
    def __init__(self, val=0, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right

def recoverFromPreorder(S: str) -> TreeNode:
    # 辅助函数:解析节点值和深度
    def parse_node(S, index):
        depth = 0
        while index < len(S) and S[index] == '-':
            depth += 1
            index += 1
        start = index
        while index < len(S) and S[index].isdigit():
            index += 1
        value = int(S[start:index])
        return value, depth, index
    
    stack = []
    index = 0
    
    while index < len(S):
        value, depth, index = parse_node(S, index)
        node = TreeNode(value)
        
        while len(stack) > depth:
            stack.pop()
        
        if stack:
            if not stack[-1].left:
                stack[-1].left = node
            else:
                stack[-1].right = node
        
        stack.append(node)
    
    return stack[0]

# 测试示例
S = "1-2--3--4-5--6--7"
root = recoverFromPreorder(S)

# 辅助函数:前序遍历打印树节点值
def print_tree_preorder(node):
    if not node:
        return
    print(node.val, end=' ')
    print_tree_preorder(node.left)
    print_tree_preorder(node.right)

# 打印还原的树
print_tree_preorder(root)

go实现

package main

import (
	"fmt"
	"strconv"
	"strings"
)

// TreeNode is a binary tree node.
type TreeNode struct {
	Val   int
	Left  *TreeNode
	Right *TreeNode
}

// recoverFromPreorder parses a preorder traversal string and constructs the binary tree.
func recoverFromPreorder(S string) *TreeNode {
	stack := []*TreeNode{}
	index := 0

	for index < len(S) {
		// Determine the depth
		depth := 0
		for index < len(S) && S[index] == '-' {
			depth++
			index++
		}

		// Determine the value
		start := index
		for index < len(S) && S[index] >= '0' && S[index] <= '9' {
			index++
		}
		val, _ := strconv.Atoi(S[start:index])

		node := &TreeNode{Val: val}

		// Ensure the stack matches the current depth
		for len(stack) > depth {
			stack = stack[:len(stack)-1]
		}

		// Attach the node to its parent
		if len(stack) > 0 {
			if stack[len(stack)-1].Left == nil {
				stack[len(stack)-1].Left = node
			} else {
				stack[len(stack)-1].Right = node
			}
		}

		// Push the current node onto the stack
		stack = append(stack, node)
	}

	// The first element in the stack is the root node
	return stack[0]
}

// Helper function to print the tree in preorder (root, left, right)
func printTreePreorder(node *TreeNode) {
	if node == nil {
		return
	}
	fmt.Print(node.Val, " ")
	printTreePreorder(node.Left)
	printTreePreorder(node.Right)
}

func main() {
	S := "1-2--3--4-5--6--7"
	root := recoverFromPreorder(S)

	printTreePreorder(root)
}

kotlin实现

class TreeNode(var `val`: Int) {
    var left: TreeNode? = null
    var right: TreeNode? = null
}

fun recoverFromPreorder(S: String): TreeNode? {
    val stack = mutableListOf<TreeNode>()
    var index = 0

    while (index < S.length) {
        // Determine the depth
        var depth = 0
        while (index < S.length && S[index] == '-') {
            depth++
            index++
        }

        // Determine the value
        val start = index
        while (index < S.length && S[index].isDigit()) {
            index++
        }
        val value = S.substring(start, index).toInt()

        val node = TreeNode(value)

        // Ensure the stack matches the current depth
        while (stack.size > depth) {
            stack.removeAt(stack.size - 1)
        }

        // Attach the node to its parent
        if (stack.isNotEmpty()) {
            if (stack.last().left == null) {
                stack.last().left = node
            } else {
                stack.last().right = node
            }
        }

        // Push the current node onto the stack
        stack.add(node)
    }

    return stack.firstOrNull()
}

// Helper function to print the tree in preorder (root, left, right)
fun printTreePreorder(node: TreeNode?) {
    if (node == null) return
    print("${node.`val`} ")
    printTreePreorder(node.left)
    printTreePreorder(node.right)
}

fun main() {
    val S = "1-2--3--4-5--6--7"
    val root = recoverFromPreorder(S)

    printTreePreorder(root)
}

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值