代码随想录算法训练营第15天|222.完全二叉树的节点个数、110.平衡二叉树、257. 二叉树的所有路径、404. 左叶子之和、可变和不可变类型

打卡Day15

  • 1.222.完全二叉树的节点个数
  • 2.110.平衡二叉树
  • 3.257. 二叉树的所有路径
  • 4.404. 左叶子之和
  • 5.可变和不可变类型区分

1.222.完全二叉树的节点个数

题目链接:222.完全二叉树的节点个数
文档讲解: 代码随想录

(1)针对普通二叉树

class Solution(object):
    def __init__(self):
        self.count = 0
    
    def countNodes(self, root):
        """
        :type root: TreeNode
        :rtype: int
        """
        if not root:
            return 0
        
        def dfs(node):
            if not node:
                return
            self.count += 1
            dfs(node.left)
            dfs(node.right)
        dfs(root)
        return self.count
class Solution(object):    
    def countNodes(self, root):
        """
        :type root: TreeNode
        :rtype: int
        """
        #后序递归遍历
        return self.getSum(root)
        
    def getSum(self, node):
        if not node:
            return 0
        leftNum = self.getSum(node.left)
        rightNum = self.getSum(node.right)
        summ = leftNum + rightNum + 1
        return summ
        
class Solution(object):    
    def countNodes(self, root):
        """
        :type root: TreeNode
        :rtype: int
        """
        #迭代法
        if not root:
            return 0
        queue = collections.deque([root])
        count = 0
        while queue:
            size = len(queue)
            for i in range(size):
                node = queue.popleft()
                count += 1
                if node.left:
                    queue.append(node.left)
                if node.right:
                    queue.append(node.right)
        return count

(2)题目中说了是完全二叉树,可以减少时间复杂度

class Solution(object):    
    def countNodes(self, root):
        """
        :type root: TreeNode
        :rtype: int
        """
        if not root:
            return 0
        left = root.left
        right = root.right
        leftDepth = 0
        rightDepth = 0
        while left:
            left = left.left
            leftDepth += 1
        while right:
            right = right.right
            rightDepth += 1
        if leftDepth == rightDepth:
            return (2 << leftDepth) - 1 #注意(2<<1) 相当于2^2,所以leftDepth初始为0
        return self.countNodes(root.left) + self.countNodes(root.right) + 1
class Solution(object):    
    def countNodes(self, root):
        """
        :type root: TreeNode
        :rtype: int
        """
        if not root:
            return 0
        count = 1 #count = 0
        left = root.left
        right = root.right
        while left and right:
            count += 1
            left = left.left
            right = right.right
        if not left and not right:
            #同时到底说明是满二叉树
            return 2 ** count - 1 #return (2 << count) - 1
        return self.countNodes(root.left) + self.countNodes(root.right) + 1

2.110.平衡二叉树

题目链接:110.平衡二叉树
文档讲解: 代码随想录

平衡二叉树:每个节点的左子树和右子树的高度差不超过1,并且左右子树也都是平衡二叉树。

思路:使用 -1 来标记已经不是平衡二叉树了,在这种情况下,再返回高度无意义。

class Solution(object):
    def isBalanced(self, root):
        """
        :type root: TreeNode
        :rtype: bool
        """
        if self.getHeight(root) == -1:
            return False
        else:
            return True
        
    def getHeight(self, node):
        if not node:
            return 0
        leftHeight = self.getHeight(node.left)
        if leftHeight == -1:
            return -1
        rightHeight = self.getHeight(node.right)
        if rightHeight == -1:
            return -1
        #判断是否左右子树深度相差不超过1
        if abs(leftHeight - rightHeight) > 1:
            return -1
        else: 
            return 1 + max(leftHeight, rightHeight)

递归精简版:

class Solution(object):
    def isBalanced(self, root):
        """
        :type root: TreeNode
        :rtype: bool
        """
        return self.getHeight(root) != -1
        
    def getHeight(self, node):
        if not node:
            return 0
        left = self.getHeight(node.left)
        right = self.getHeight(node.right)
        if left == -1 or right == -1 or abs(left - right) > 1:
            return -1
        return 1 + max(left, right)

迭代法:
这道题需要通过求传入节点为根节点的最大深度来求高度,采用后序遍历的方式,求高度不能使用层序遍历,这里使用二叉树的统一迭代方式。

class Solution(object):
    def isBalanced(self, root):
        """
        :type root: TreeNode
        :rtype: bool
        """
        st = []
        if not root:
            return True
        st.append(root)
        while st:
            node = st.pop()
            if abs(self.get_height(node.left) - self.get_height(node.right)) > 1:
                return False
            if node.right:
                st.append(node.right)
            if node.left:
                st.append(node.left)
        return True
        
        
    def get_height(self, cur):
        stack = []
        if cur:
            stack.append(cur)

        res = 0
        depth = 0

        while stack:
            node = stack.pop()
            if node:
                stack.append(node)
                stack.append(None)
                depth += 1
                if node.right:
                    stack.append(node.right)
                if node.left:
                    stack.append(node.left)
            else:
                stack.pop()
                depth -= 1
            res = max(res, depth)
        return res

迭代精简版:使用字典记录节点的高度。

class Solution(object):
    def isBalanced(self, root):
        """
        :type root: TreeNode
        :rtype: bool
        """
        if not root:
            return True
        st = []
        st.append(root)
        height_map = {}
        while st:
            node = st.pop()
            if node:
                st.append(node)
                st.append(None)
                if node.right: st.append(node.right)
                if node.left: st.append(node.left)
            else:
                real_node = st.pop()
                left = height_map.get(real_node.left, 0)
                right = height_map.get(real_node.right, 0)
                if abs(left - right) > 1:
                    return False
                height_map[real_node] = 1 + max(left, right)
        return True

3.257. 二叉树的所有路径

题目链接:257. 二叉树的所有路径
文档讲解: 代码随想录

递归法:一定记得要回溯!

class Solution(object):
    def binaryTreePaths(self, root):
        """
        :type root: TreeNode
        :rtype: List[str]
        """
        res = []
        path = []
        if not root:
            return res
        self.traversal(root, path, res)
        return res

    def traversal(self, cur, path,res):
        #因为不需要遍历到空节点,所以在判断是否为叶子节点前就将该节点存入路径中
        path.append(cur.val)
        if not cur.left and not cur.right:
            spath = '->'.join(map(str, path))
            res.append(spath)
            return 
        if cur.left:
            self.traversal(cur.left, path, res)
            path.pop()#回溯
        if cur.right:
            self.traversal(cur.right, path, res)
            path.pop()
class Solution(object):
    def binaryTreePaths(self, root):
        """
        :type root: TreeNode
        :rtype: List[str]
        """
        path = ''
        res = []
        if not root:
            return res
        self.taversal(root, path, res)
        return res
    
    def taversal(self, cur, path, res):
        path += str(cur.val)
        if not cur.left and not cur.right:
            res.append(path)
        if cur.left:
            self.taversal(cur.left, path + '->', res)#隐形回溯,和之前depth + 1是一个道理
        if cur.right:
            self.taversal(cur.right, path + '->', res)
class Solution(object):
    def binaryTreePaths(self, root):
        """
        :type root: TreeNode
        :rtype: List[str]
        """
        res = []
        if not root:
            return res
        self.traversal(root, [], res)
        return res

    def traversal(self, cur, path, res):
        path.append(cur.val)
        if not cur.left and not cur.right:
            spath = '->'.join(map(str, path))
            res.append(spath)
            return
        if cur.left:
            self.traversal(cur.left, path[:], res)#建立副本,隐形回溯
        if cur.right:
            self.traversal(cur.right, path[:], res)

迭代法:

class Solution(object):
    def binaryTreePaths(self, root):
        """
        :type root: TreeNode
        :rtype: List[str]
        """
        if not root:
            return []
        stack = [root]
        path_st = [str(root.val)]
        res = []
        while stack:
            cur = stack.pop()
            path = path_st.pop()
            if not (cur.left or cur.right):
                res.append(path)
            if cur.right:
                stack.append(cur.right)
                path_st.append(path + '->' + str(cur.right.val))
            if cur.left:
                stack.append(cur.left)
                path_st.append(path + '->' + str(cur.left.val))
        return res

4.404. 左叶子之和

题目链接:404. 左叶子之和
文档讲解: 代码随想录

难点就是如何判断是否为左叶子节点:必须要通过节点的父节点来判断其左孩子是不是左叶子。如果该节点的左节点不为空,该节点的左节点的左节点为空,该节点的左节点的右节点为空,则找到了一个左叶子。采用后序遍历,统计左子树,再统计右子树,最后相加。

class Solution(object):
    def sumOfLeftLeaves(self, root):
        """
        :type root: TreeNode
        :rtype: int
        """
        if not root:
            return 0
        if not root.left and not root.right:
            return 0
        
        leftValue = self.sumOfLeftLeaves(root.left)

        #判断左子树是否为左叶子
        if root.left and not root.left.left and not root.left.right:
            leftValue = root.left.val
        
        rightValue = self.sumOfLeftLeaves(root.right)
        summ = leftValue + rightValue
        return summ

递归精简版:

class Solution(object):
    def sumOfLeftLeaves(self, root):
        """
        :type root: TreeNode
        :rtype: int
        """
        if not root:
            return 0
        leaveValue = 0
        if root.left and not root.left.left and not root.left.right:
            leaveValue = root.left.val
        return leaveValue + self.sumOfLeftLeaves(root.left) + self.sumOfLeftLeaves(root.right)

迭代法:

class Solution(object):
    def sumOfLeftLeaves(self, root):
        """
        :type root: TreeNode
        :rtype: int
        """
        if not root:
            return 0
        stack = []
        stack.append(root)
        
        num = 0
        while stack:
            node = stack.pop()
            if node.left and not node.left.left and not node.left.right:
                num += node.left.val
            if node.right:
                stack.append(node.right)
            if node.left:
                stack.append(node.left)
        return num

5.可变和不可变类型区分

有两个例子:代码正确与否不论

class Solution():
    def preorderTraversal(self, root):
        ans = []  
        def Traversal(root):
            if not root: return
            ans.append(root.val)
            Traversal(root.left)
            Traversal(root.right)
        Traversal(root)
        return ans
class Solution:
    def sumofLeftLeaves(self,root):
        def isLeftLeaf(root):return root and not root.left and not root.right
        res = 0
        def dfs(root):
            if not root:return 0
            if isLeftLeaf(root.left):
                res = res + root.left.val
            dfs(root.left)
        dfs(root)
        return res

在运行第二个代码的时候会报错,原因是因为 res 是不可变类型,第一个代码中 ans 可以传入的原因是它是可变类型。

在 Python 中,列表(list)、字典(dict)、集合(set)、字节数组(bytearray)等是可变类型,因为它们的内容可以修改。而整数(int)、浮点数(float)、字符串(str)、元组(tuple)等则是不可变类型,因为它们的值一旦设定就不能更改。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/784092.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Qt 进程间通信(一)——QSharedMemory共享内存

QSharedMemory共享内存 序言环境理论—逻辑理解实战—代码读取示例写入示例 序言 讲讲Qt的共享内存吧&#xff0c;巩固下 环境 msvc2022 Qt5.15 参考文档&#xff1a;https://doc.qt.io/qt-5/qsharedmemory.html 理论—逻辑理解 看下面前&#xff0c;你需要将共享内存看成…

【设计模式】观察者模式(定义 | 特点 | Demo入门讲解)

文章目录 定义结构Demo | 代码Subject目标类Observer抽象观察者观察者1 | CPU监听器观察者2 | 内存监听器客户端 | Client 优点适合场景 定义 所谓观察者模式就是你是被观察的那个对象&#xff0c;你爸爸妈妈就是观察者&#xff0c;一天24h盯着你&#xff0c;一旦你不听话&…

NFT 技术在艺术领域的应用

NFT (Non-Fungible Token) 技术在艺术领域有着广泛的应用&#xff0c;为艺术家和艺术品收藏家带来了新的机遇和挑战。以下是 NFT 技术在艺术领域的一些主要应用。北京木奇移动技术有限公司&#xff0c;专业的软件外包开发公司&#xff0c;欢迎交流合作。 1. 数字艺术品确权和交…

spring mvc学习

第四章 Spring MVC 第一节 Spring MVC 简介 1. Spring MVC SpringMVC是一个Java 开源框架&#xff0c; 是Spring Framework生态中的一个独立模块&#xff0c;它基于 Spring 实现了Web MVC&#xff08;数据、业务与展现&#xff09;设计模式的请求驱动类型的轻量级Web框架&am…

C#-反射

一、概念 反射&#xff08;Reflection&#xff09;在C#中是一种非常重要的特性&#xff0c;它为开发者提供了在运行时获取和操作关于类型、成员、属性、方法等的详细信息的能力。通过反射&#xff0c;开发者可以在程序运行期间动态地创建对象、调用方法、设置属性值以及进行其…

【免费数字孪生平台】零代码制作智慧农业蔬菜大棚可视化

一&#xff0e;智慧农业的价值 智慧农业&#xff0c;作为农业中的智慧经济形态&#xff0c;是现代科学技术与农业种植深度融合的产物。它通过将物联网、云计算、大数据、人工智能等现代信息技术集成应用于农业生产中&#xff0c;实现了农业生产的无人化、自动化和智能化管理。…

考CISP,不要踩坑的几点建议

当你立志要在信息安全领域闯出一片天&#xff0c;可能多少都会听行内人说&#xff0c;搞本CISP。但这个认证究竟该怎么拿&#xff1f;需要培训吗&#xff1f;培训又是怎么一回事&#xff1f;价格如何&#xff1f;还有&#xff0c;什么时候开始准备最好&#xff1f;这些问题可能…

为什么看起来很低智商的广告比高大上的广告转化效果更好?

大家在刷抖音的时候&#xff0c;是不是总能刷到一些看起来很低质、很尴尬的广告&#xff0c;或者说是一些毫无吸引力的小说剧情&#xff1f;这些广告和内容让人忍不住怀疑&#xff0c;为什么这么低级的广告竟然会有人点击&#xff1f;其实&#xff0c;这背后有着深刻的营销策略…

BJT的结构(晶体管电压/电流+β+晶体管特性曲线/截止与饱和+直流负载线(Q点))+单片机数码管基础

2024-7-8&#xff0c;星期一&#xff0c;20:23&#xff0c;天气&#xff1a;晴&#xff0c;心情&#xff1a;晴。今天没有什么特殊的事情发生&#xff0c;周末休息了两天&#xff0c;周一回来继续学习啦&#xff0c;加油加油&#xff01;&#xff01;&#xff01; 今日完成模电…

HAProxy安装配置详解

HAProxy是一个使用C语言编写的自由及开放源代码软件&#xff0c;其提供高可用性、负载均衡&#xff0c;以及基于TCP和HTTP的应用程序代理。   HAProxy特别适用于那些负载特大的web站点&#xff0c;这些站点通常又需要会话保持或七层处理。HAProxy运行在当前的硬件上&#xf…

珍藏多年的计算机内核结构大全笔记,掌握计算机工作原理真不难

本篇会加入个人的所谓鱼式疯言 ❤️❤️❤️鱼式疯言:❤️❤️❤️此疯言非彼疯言 而是理解过并总结出来通俗易懂的大白话, 小编会尽可能的在每个概念后插入鱼式疯言,帮助大家理解的. &#x1f92d;&#x1f92d;&#x1f92d;可能说的不是那么严谨.但小编初心是能让更多人…

大模型面试笔试常见问题汇总(精心准备)

1 GPT和Bert的区别? 1.模型结构和训练方式 BERT通过掩码语言模型(Masked Language Model, MLM)和下一句预测(Next Sentence Prediction, NSP)任务进行训练: 掩码语言模型(MLM):在输入序列中,BERT随机掩盖一些词语,并要求模型预测这些被掩盖的词语。这使得BERT能够学…

TCP的p2p网络模式

TCP的p2p网络模式 1、tcp连接的状态有以下11种 CLOSED&#xff1a;关闭状态LISTEN&#xff1a;服务端状态&#xff0c;等待客户端发起连接请求SYN_SENT&#xff1a;客户端已发送同步连接请求&#xff0c;等待服务端相应SYN_RECEIVED&#xff1a;服务器收到客户端的SYN请请求&…

214.贪心算法:K次取反后最大化的数组和(力扣)

class Solution { public:int largestSumAfterKNegations(vector<int>& nums, int k) {int sum 0;// 进行k次取反操作while (k > 0){// 对数组进行排序sort(nums.begin(), nums.end());// 将最小的元素取反nums[0] -nums[0];// 减少k的值k--;}// 计算数组的总和…

学习数据库2

在数据库中创建一个表student&#xff0c;用于存储学生信息 查看建表结果 向student表中添加一条新记录 记录中id字段的值为1&#xff0c;name字段的值为"monkey"&#xff0c;grade字段的值为98.5 并查看结果 向student表中添加多条新记录 2,"bob"…

水利水库大坝结构安全自动化监测主要测哪些内容?

在大坝安全自动化监测系统建设中&#xff0c;应根据坝型、坝体结构和地质条件等因素选定监测项目&#xff1b;主要监测对象包括坝体、坝基及有关的各种主要水工建筑物、大坝附近的不稳定岸坡和大坝周边的气象环境。深圳安锐科技建议参考下列表格适当调整。 &#xff08;一&am…

预训练对齐:数学理论到工程实践的桥梁

在人工智能和机器学习领域&#xff0c;预训练模型的对齐是一个至关重要的概念。本篇博客源自听了一场黄民烈老师关于大模型对齐的分享&#xff0c;整理内容如下&#xff0c;供大家参考。 数学理论中的预训练对齐 数学理论上&#xff0c;预训练对齐是什么&#xff1f; 序列…

比赛获奖的武林秘籍:04 电子类比赛嵌入式开发快速必看的上手指南

比赛获奖的武林秘籍&#xff1a;04 电子类比赛嵌入式开发快速必看的上手指南 摘要 本文主要介绍了电子类比赛中负责嵌入式开发同学的上手比赛的步骤、开发项目的流程和具体需要学习的内容&#xff0c;并结合自身比赛经历给出了相关建议。 正文 如何开始上手做自己第一个项目…

STM32中的DMA:解锁高效数据传输的秘密武器(内附实例)

目录 引言 理解DMA&#xff1a;数据的高效搬运工 DMA的主要特性 多优先级请求 事件标志 数据对齐 多样化的数据传输路径 广泛的数据源与目标 最大数据长度 DMA寄存器详解 增量与循环模式 DMA中断机制 ​编辑 小实验&#xff1a;DMA-ADC串口发送 引言 在现代嵌入…

推荐一款Win11主题WPF UI框架

最近在微软商店&#xff0c;官方上架了新款Win11风格的WPF版UI框架【WPF Gallery Preview 1.0.0.0】,这款应用引入了前沿的Fluent Design UI设计&#xff0c;为用户带来全新的视觉体验。 WPF Gallery简介 做为一关注前沿资讯的开发人员&#xff0c;首先关注的是应用WPF Gallery…