python_ACM模式《剑指offer刷题》二叉树2

题目:

面试tips:

面试官有可能问到:

如果你需要频繁地查找第 k 小的值,你将如何优化算法?(见思路三)

思路:

思路一:二叉搜索树最大的特点就是中序遍历是递增的。因此最容易想到的是对二叉树进行中序遍历存入数组中,再遍历数组至第k个数,就是二叉树的第k小的数/节点。这样的时间复杂度就是O(N+K),空复为O(N)。显然不是最优。

思路二:在思路一的基础上不采用数组,直接对二叉搜索树进行中序遍历,在遍历的过程中目标是找到第k个小的节点。此时因为是中序要先遍历到最左节点后再退回遍历k个,因此最理想(即二叉搜索树为平衡二叉树)的时复为O(logN+K),最不理想(此二叉搜索树没有右子树)才达到O(N+K),此方法需要用到栈或递归(因为其遍历到的节点并不处理,它要遍历到最左节点再从最左节点开始处理,是一个后进先出的处理思想)因此需要用到递归或栈,因此空复最理想为O(logN),最不理想为O(N). 已经比思路一好很多了。

思路三:虽然思路二已经好很多,且觉得应付大部分面试应该没问题。但如果需要频繁查找第k小的值,要如何优化?(这是从leetcode上看来的)觉得有点意思。这个思路是如果能知道以node为根节点的子树有多少个节点(假设存为了一个字典node_count),则起初node = root。如果node_count[node] < k-1, 则等价于找node.right的第k - (left + 1)个节点;如果node_count[node] == k-1, 则node即为第k个节点;如果node_count[node] > k-1, 则等价于找node.left的第k个节点,一直下去直至找到为止。显然这里就需要预处理node_count,遍历整颗二叉搜索树,统计以每个节点node为根节点的子树的节点个数存入字典中,时复O(N), 空复O(N). 后多次查询第k小的节点时时复最理解为O(logN),最不理想为O(N).

代码实现:

思路一略

思路二的迭代法:

class TreeNode:def __init__(self, val=0, left=None, right=None):self.val = valself.left = leftself.right = rightdef arr2tree(arr, index):# 满二叉树数组格式构造二叉树# 构造arr[index]的二叉树# 满二叉树数组格式: 是指首先按层序遍历顺序,且二叉树的非空节点的左右孩子(尽管为空)都会打印出来,空节点的左右孩子则不打印if index >= len(arr) or arr[index] == None:return Noneroot = TreeNode(val = arr[index])left = arr2tree(arr, 2 * index + 1)right = arr2tree(arr, 2 * index + 2)root.left = leftroot.right = rightreturn rootclass Solution:def kthSmallest(self, root, k) :# 刚才中序遍历递归法查找# 现用中序遍历的迭代法查找第k小的数# 题中说明没有非空的情况 因此不对非空进行处理stack = [root]while stack:node = stack.pop()if node:# 如果不是空 说明第一次遍历至此,用None标记是第二次遍历到此时才开始处理# 中序 为左中右,因此存入栈中是右中左if node.right:stack.append(node.right)stack.append(node)stack.append(None)if node.left:stack.append(node.left)else:node = stack.pop()# 每遇到一个None时 说明这个节点被遍历第二次了 即开始处理了k -= 1if k == 0:return node.valif __name__ == '__main__':arr = [5, 3, 6, 2, 4, None, None, 1]k = 3root = arr2tree(arr, 0)a = Solution()print(a.kthSmallest(root, k))  # 3

思路二的递归法:

class TreeNode:def __init__(self, val=0, left=None, right=None):self.val = valself.left = leftself.right = rightdef arr2tree(arr, index):# 满二叉树数组格式构造二叉树# 构造arr[index]的二叉树# 满二叉树数组格式: 是指首先按层序遍历顺序,且二叉树的非空节点的左右孩子(尽管为空)都会打印出来,空节点的左右孩子则不打印if index >= len(arr) or arr[index] == None:return Noneroot = TreeNode(val = arr[index])left = arr2tree(arr, 2 * index + 1)right = arr2tree(arr, 2 * index + 2)root.left = leftroot.right = rightreturn rootclass Solution:def __init__(self):# 初始化全局变量,这里让self.k作为全局变量是想找整棵树上第k小的数self.k = -1self.result = -1def kthSmallest(self, root, k: int):# 直接在二叉树中找第k小的元素def dfs(root):# 找以root为根节点的第k小的数,找到就【更新】self.result并返回,此函数只需更新因此不用返回值# 终止条件if not root:return# 单层dfs(root.left)self.k -= 1if self.k == 0:self.result = root.valdfs(root.right)self.k = kdfs(root)return self.resultif __name__ == '__main__':arr = [5, 3, 6, 2, 4, None, None, 1]k = 3root = arr2tree(arr, 0)a = Solution()print(a.kthSmallest(root, k))

思路三:

class TreeNode:def __init__(self, val=0, left=None, right=None):self.val = valself.left = leftself.right = rightdef arr2tree(arr, index):# 满二叉树数组格式构造二叉树# 构造arr[index]的二叉树# 满二叉树数组格式: 是指首先按层序遍历顺序,且二叉树的非空节点的左右孩子(尽管为空)都会打印出来,空节点的左右孩子则不打印if index >= len(arr) or arr[index] == None:return Noneroot = TreeNode(val = arr[index])left = arr2tree(arr, 2 * index + 1)right = arr2tree(arr, 2 * index + 2)root.left = leftroot.right = rightreturn rootclass pre_do:def __init__(self, root):self.root = rootself.count_node = {}self.cal_count_node(root)def cal_count_node(self, node):# 得到预处理好的self.count_node字典--后序遍历# 统计以子树中某个节点 为根节点的子树的节点个数# 注意这里如果node为空是不会被存到字典中,因此后面get时要对空作特殊处理if not node:return 0self.count_node[node] = 1 + self.cal_count_node(node.left) + self.cal_count_node(node.right)return self.count_node[node]def get_count_node(self, node):return self.count_node[node] if node else 0def find_kthSmallest(self, k):node = self.rootwhile node:left_count = self.get_count_node(node.left)if left_count < k - 1:node = node.rightk -= left_count + 1elif left_count == k - 1:return node.valelse:node = node.leftclass Solution:def kthSmallest(self, root, k: int) -> int:result = pre_do(root)return result.find_kthSmallest(k)if __name__ == '__main__':arr = [5, 3, 6, 2, 4, None, None, 1]k = 3root = arr2tree(arr, 0)a = Solution()print(a.kthSmallest(root, k))  # 3

参考资料:

1. 《剑指offer》

2. 力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

蓝桥杯每日一题------背包问题(一)

背包问题 阅读小提示&#xff1a;这篇文章稍微有点长&#xff0c;希望可以对背包问题进行系统详细的讲解&#xff0c;在看的过程中如果有任何疑问请在评论区里指出。因为篇幅过长也可以进行选择性阅读&#xff0c;读取自己想要的那一部分即可。 前言 背包问题可以看作动态规…

CTFSHOW命令执行web入门29-54

description: >- 这里就记录一下ctfshow的刷题记录是web入门的命令执行专题里面的题目,他是有分类,并且覆盖也很广泛,所以就通过刷这个来,不过里面有一些脚本的题目发现我自己根本不会笑死。 如果还不怎么知道写题的话,可以去看我的gitbook,当然csdn我也转载了我自己的…

幻兽帕鲁服务器怎么更新?如何快速在腾讯云更新幻兽帕鲁Palworld服务器,显示版本不兼容怎么解决

幻兽帕鲁服务器怎么更新&#xff1f;如何快速在腾讯云更新幻兽帕鲁Palworld服务器&#xff0c;显示版本不兼容怎么解决。最近的幻兽帕鲁服务器又更新了。 如何在不需要远程登录服务器的情况下&#xff0c;通过一行命令来更新幻兽帕鲁呢&#xff1f; 腾讯云轻量云一键部署幻兽…

今年春节,德施曼成“春晚御用”智能锁,亮相总台春晚直播间

总台春晚&#xff0c;是每年春节期间的最大热点。 今年除夕夜&#xff0c;高端智能锁品牌德施曼&#xff0c;不仅成为“春晚御用”智能锁&#xff0c;还将旗下的哨兵猫眼智能锁&#xff0c;卖到了总台春晚的直播间里。龙年春节&#xff0c;德施曼智能锁携手小红书《大家的春晚》…

金融信贷风控评分卡模型

评分卡模型概念 评分模型是根据借款人的历史数据&#xff0c;选取不同维度的数据类型&#xff0c;通过计算而得出的对借款人信用情况打分的模型。不同等级的信用分数代表了借款人信用情况的好坏&#xff0c;以此来分析借款人按时还款的可能性。 评分卡模型分类 A卡&#xff…

今日早报 每日精选15条新闻简报 每天一分钟 知晓天下事 2月10日,星期六

每天一分钟&#xff0c;知晓天下事&#xff01; 2024年2月10日 星期六 农历正月初一 春节 1、 国务院&#xff1a;到2025年&#xff0c;初步建成覆盖各领域、各环节的废弃物循环利用体系。 2、 国家移民管理局&#xff1a;部分国家人员可以用更多事由免签入境海南。 3、 市场…

css的布局(BFC)

一、css中常规的定位方案 1、普通流 元素按照其在HTML中的先后位置自上而下布局。 行内元素水平排列&#xff0c;当行被占满后换行&#xff1b;块级元素则会被渲染为完整的一行。 所有元素默认都是普通流定位。 2、浮动 元素首先按照普通流的位置出现&#xff0c; 然后根据浮动…

跟着cherno手搓游戏引擎【23】项目维护、2D引擎之前的一些准备

项目维护&#xff1a; 修改文件结构&#xff1a; 头文件自己改改就好了 创建2DRendererLayer&#xff1a; Sandbox2D.h: #pragma once #include "YOTO.h" class Sandbox2D :public YOTO::Layer {public:Sandbox2D();virtual ~Sandbox2D() default;virtual void O…

图神经网络与图表示学习: 从基础概念到前沿技术

目录 前言1 图的形式化定义和类型1.1 图的形式化定义1.2 图的类型 2 图表示学习2.1 DeepWalk: 融合语义相似性与图结构2.2 Node2Vec: 灵活调整随机游走策略2.3 LINE: 一阶与二阶邻接建模2.4 NetMF: 矩阵分解的可扩展图表示学习2.5 Metapath2Vec: 异构图的全面捕捉 3 图神经网络…

【正式】今年第一篇CSDN(纯技术教学)

一、文件上传简介 文件上传漏洞是指用户上传了一个可执行的脚本文件&#xff08;木马、病毒、恶意脚本、webshell等&#xff09;&#xff0c;并通过此脚本文件获得了执行服务器端命令的能力。上传点一般出现在头像、导入数据、上传压缩包等地方&#xff0c;由于程序对用户上传…

TOP100 二叉树(三)

11.114. 二叉树展开为链表 给你二叉树的根结点 root &#xff0c;请你将它展开为一个单链表&#xff1a; 展开后的单链表应该同样使用 TreeNode &#xff0c;其中 right 子指针指向链表中下一个结点&#xff0c;而左子指针始终为 null 。展开后的单链表应该与二叉树 先序遍历 顺…

SegmentAnything官网demo使用vue+python实现

一、效果&准备工作 1.效果 没啥好说的&#xff0c;低质量复刻SAM官网 https://segment-anything.com/ 需要提一点&#xff1a;所有生成embedding和mask的操作都是python后端做的&#xff0c;计算mask不是onnxruntime-web实现的&#xff0c;前端只负责了把rle编码的mask解…

5G技术对物联网的影响

随着数字化转型的加速&#xff0c;5G技术作为通信领域的一次重大革新&#xff0c;正在对物联网&#xff08;IoT&#xff09;产生深远的影响。对于刚入行的朋友们来说&#xff0c;理解5G技术及其对物联网应用的意义&#xff0c;是把握行业发展趋势的关键。 让我们简单了解什么是…

巧用liteflow,告别if else,SpringBoot整合liteflow

假设有一个三个原子业务&#xff0c;吃饭、喝水、刷牙。 现在有三个场景&#xff0c;分别是 场景A: 吃饭->刷牙->喝水 官网地址&#xff1a;https://liteflow.cc/ 1.添加依赖&#xff1a; <dependency><groupId>com.yomahub</groupId><artifactI…

基于鲲鹏服务NodeJs安装

准备工作 查看当前环境 uname -a查看鲲鹏云CPU架构 cat /proc/cpuinfo# 查看CPU architecture项&#xff0c;8表示v8&#xff0c;7表示v7下载Node.js NodeJs 选择 Linux Binaries (ARM) ARMv8 wget -c https://nodejs.org/dist/v12.18.3/node-v12.18.3-linux-arm64.tar.xz…

基于完全二叉树实现线段树-- [爆竹声中一岁除,线段树下苦踌躇]

文章目录 一.完全二叉树完全二叉树的父子结点引索关系 二.线段树三.基于完全二叉树实现线段树关于线段树的结点数量问题的证明递归建树递归查询区间和递归单点修改线段树模板题 一.完全二叉树 完全二叉树的物理结构是线性表,逻辑结构是二叉树 完全二叉树的父子结点引索关系 …

OpenCV与机器学习:使用opencv和sklearn实现线性回归

前言 线性回归是一种统计分析方法&#xff0c;用于确定两种或两种以上变量之间相互依赖的定量关系。在统计学中&#xff0c;线性回归利用线性回归方程&#xff08;最小二乘函数&#xff09;对一个或多个自变量&#xff08;特征值&#xff09;和因变量&#xff08;目标值&#…

深度优先搜索(DFS)与广度优先搜索(BFS):探索图与树的算法

一、引言 在图论和树形结构中&#xff0c;搜索算法是寻找从起点到终点的路径的关键。其中&#xff0c;深度优先搜索&#xff08;DFS&#xff09;和广度优先搜索&#xff08;BFS&#xff09;是最常用且最基础的两种搜索算法。本文将详细介绍广度优先搜索&#xff08;BFS&#xf…

一文彻底搞懂Kafka如何保证消息不丢失

文章目录 1. kafka 架构2. producer端是如何保证数据不丢失的2.1 同步发送2.2 异步发送2.3 批量发送 3. consumer端是如何保证数据不丢失的3.1 手动提交3.2 幂等性消费 4. broker端是如何保证数据不丢失的4.1 副本机制4.2 ISR机制4.3 刷盘机制 1. kafka 架构 Producer&#xff…

ES6 ~ ES11 学习笔记

课程地址 ES6 let let 不能重复声明变量&#xff08;var 可以&#xff09; let a; let b, c, d; let e 100; let f 521, g "atguigu", h [];let 具有块级作用域&#xff0c;内层变量外层无法访问 let 不存在变量提升&#xff08;运行前收集变量和函数&#…