IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 【二叉树】验证二叉树的前序序列化 -> 正文阅读

[数据结构与算法]【二叉树】验证二叉树的前序序列化

0x00 题目

序列化二叉树的一种方法是使用 前序遍历
当遇到一个 非空 节点时,可以记录下这个节点的值
如果它是一个 节点,可以使用一个标记值记录,例如 #

给定一串以 逗号 分隔的序列
验证它是否是 正确 的二叉树的 前序 序列化
编写一个在 重构树的条件下的可行算法

每个以逗号分隔的字符,是一个整数
或者是一个表示 null 指针的 #
你可以认为输入格式总是有效的
例如它永远不会包含两个连续的逗号,比如 1,,3


0x01 思路

方法一:

先定义一个概念,叫做 槽位

一个 槽位 可以被看作当前二叉树中正在等待 被节点填充 的那些位置

二叉树的建立也伴随着 槽位 数量的变化。每当遇到一个节点时:
a.如果遇到了 节点,则要 消耗 一个槽位
b.如果遇到了 非空 节点,则除了 消耗 一个槽位外,还要再 补充 两个槽位

使用栈来维护槽位的变化
栈中的每个 元素,代表了对应节点处剩余槽位的 数量
而栈顶元素就对应着下一步可用的槽位数量

当遇到 节点时,仅将栈顶元素减 1
当遇到 非空 节点时,将栈顶元素减 1 后,再向栈中压入一个 2

无论何时,如果栈顶元素变为 0,就立刻将栈顶 弹出
遍历结束后,若栈 为空
说明没有待填充的槽位,因此是一个 合法 序列

否则若栈 不为空,则序列不合法
此外,在遍历的过程中,若槽位数量 不足,则序列不合法


方法二:计数

能否将方法一的空间复杂度优化至 O(1) 呢?
回顾方法一的逻辑,如果把栈中元素看成一个 整体
即所有剩余槽位的 数量,也能维护槽位的 变化

因此,只维护一个 计数器,代表栈中所有元素之
其余的操作逻辑均可以保持不变


0x02 解法

语言:Swift

解法一:

func isValidSerialization(_ preorder: String) -> Bool {
    let n = preorder.count
    var i = 0
    var stack: [Int] = [1]
    
    while i < n {
    	// 槽位数量不足
        if stack.isEmpty {
            return false
        }
        
        // 取一个字符
        let sIndex = preorder.startIndex
        var index = preorder.index(sIndex, offsetBy: i)
        let c = preorder[index]
        
        // 判断字符
        if c == "," {
            i += 1
        }else if c == "#" {
        	// 空节点
            let last = stack.last! - 1
            if last == 0 {
                stack.removeLast()
            }else{
                stack[stack.count-1] = last
            }
            i += 1
        }else{
            // 读一个数字
            var s = Character("c")
            while i < n && s != "," {
                index = preorder.index(sIndex, offsetBy: i)
                s = preorder[index]
                i += 1
            }
            
            let last = stack.last! - 1
            if last == 0 {
                stack.removeLast()
            }else{
                stack[stack.count-1] = last
            }
            stack.append(2)
        }
    }
    return stack.isEmpty
}

解法二:

func isValidSerializationV2(_ preorder: String) -> Bool {
    let n = preorder.count
    var i = 0
    var slots = 1
    
    while i < n {
        if slots == 0 {
            return false
        }
        
        let sIndex = preorder.startIndex
        var index = preorder.index(sIndex, offsetBy: i)
        let c = preorder[index]
        
        if c == "," {
            i += 1
        }else if c == "#" {
            slots -= 1
            i += 1
        }else{
            // 读一个数字
            var s = Character("c")
            while i < n && s != "," {
                index = preorder.index(sIndex, offsetBy: i)
                s = preorder[index]
                i += 1
            }
            slots += 1 // slots = slots - 1 + 2
        }
    }
    return slots == 0
}


小笔记应用

请添加图片描述


  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-02-26 11:55:08  更:2022-02-26 11:56:29 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 16:41:16-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码