【代码随想录】二叉树(1)
前言:最近一个学习小组里大家约定每天刷算法题(虽然近期因为题目难度变难变为了两天一道),没想到的是几个组员居然不约而同地说出了代码随想录这个名字,正是“英雄所见略同”,最近已经是刷了有一阵子了,期间虽然偶然有做笔记,又因为这样那样的事情写得断断续续很零碎,实在凑不出一篇博客来,最近写到了二叉树,有了些感悟和时间,正好整理出篇博客来记录。
代码随想录:https://www.programmercarl.com/
二叉树二叉树的递归遍历递归:在函数的定义中使用函数自身的方法
因为二叉树的左右子树还是二叉树,所以可以使用递归的方法。前中后序遍历时使用递归则可以写出非常简洁优美的代码,并且在前中后切换时也仅仅只需要改变几行代码之间的顺序,代码的结构是保持不变的。
// 前序遍历·递归·LC144_二叉树的前序遍历class Solution { public List<Integer> preorderTraversal(TreeNode root) { List<Integer> result = new ArrayList& ...
【数据结构】动态查找表
动态查找表动态查找表,表结构本身是在查找过程中动态生成的,动态更新意味着适合使用指针
二叉排序树二叉排序树:构造的过程就是排序的过程,在无序的关键字序列中,在既有的二叉排序树(一开始的二叉排序树是一个空树)中查询一个个关键字应该所在的位置,往二叉排序树一个个添加,最后只需要对生成的二叉排序树进行中序遍历就可以得到有序的关键字序列了
在实际应用中,平衡二叉树有其弊端——在数据量大的情况下深度太大,因为每当访问一个节点的时候,我们需要进行更多的比较(每层都要比较选择进入哪个子树),不过消耗时间主要不是在内存中元素之间的比较,而是每次进入一个节点时都需要进行磁盘I/O读取,那么为了减少时间消耗,我们现在需要的就是尽量减少树的深度,引入B-树这种数据结构
B-树B-树要尽量减少树的深度,为了达到这个目的,B-树增加了可拥有子节点的上限;还有要提高每个节点的利用率(不要存储太少的元素),设置一个下限,每个节点的子节点(M个)保持在 (m/2)-1(向上取整)<= M <= m 之间,下限取m/2(向上取整)-1是考虑到节点之间的合并操作,低于m/2才能进行合并操作,合并时候 ...
TodoList日志(1)
TodoList设计这是创新实践课程的作业,做一个简单的TodoList应用,借这个机会把整个业务开发的流程熟悉一遍。
需求分析功能调研TODO 应用通常是一个帮助用户管理日常任务的工具,用户可以在其中创建、查看、编辑、删除任务,并通过标记任务状态来追踪进度。常见的功能包括:
创建任务:允许用户输入任务标题、描述、优先级、截止日期等信息。
查看任务:展示所有任务,并按状态(如已完成、未完成)进行过滤。
编辑任务:让用户修改任务的内容、截止日期等。
删除任务:删除已不再需要的任务。
标记任务完成/未完成:允许用户标记任务的完成状态,帮助跟踪进度。
此外,一些TODO应用还可能包括任务提醒、优先级设置、任务分类、搜索功能等扩展功能。
核心功能
这些是项目的基本功能,优先实现基本功能,扩展功能之后再说。
创建任务:用户可以添加新的任务,任务包含标题、描述和截止日期(可选)。任务可以标记为已完成或未完成。
输入框:任务标题、任务描述、截止日期。
按钮:保存、取消。
查看任务:用户可以查看所有任务,并过滤选项:全部任务、未完成任务、已完成任务。。
列表展示:任务标题、描述、状 ...
【青训营X豆包MarsCode】第六课-走进消息队列
走进消息队列消息队列前世今生在现代分布式系统中,消息队列(Message Queue,简称 MQ)已成为一种不可或缺的中间件,用于解耦系统组件、提高系统可靠性与扩展性。消息队列的出现和发展,与以下几个系统问题密切相关:
系统崩溃:
在高并发系统中,直接处理请求可能导致系统崩溃。通过将请求先放入消息队列,系统可以避免瞬时过载,确保稳定运行,等待后端存储服务逐步处理这些请求。
服务处理能力有限:
当系统的处理能力达到瓶颈时,前端请求会迅速堆积,造成系统崩溃。此时可以将请求放入消息队列,按需逐步消费,避免一瞬间的请求涌入导致服务过载。
链路耗时长尾:
在一些分布式系统中,某些链路的处理时间可能会较长,导致长尾效应。通过异步方式将请求投递到消息队列中,避免长时间等待影响系统整体性能。
日志存储:
在分布式系统中,日志的存储与分析是关键环节。将日志数据发送到消息队列后,后端日志分析平台可以异步获取数据,进行实时或定期分析。
什么是消息队列?
消息队列(MQ)是一个用于存储和传输消息的容器,其本质上是一个先进先出(FIFO)的队列。在分布式系统中,消息队列通常具有以下特点:
高吞 ...
【青训营X豆包MarsCode】第五课-TOS 对象存储实战
TOS 对象存储实战对象存储基本介绍抖音背后的存储发/刷抖音背后有何流程?背后有何种存储需求?
短视频生产/消费
片源系统–>审核系统–>推送系统
片源系统:用户上传的原始视频文件。
审核系统:对视频内容进行审核和检测。
推送系统:审核通过后,视频被推送至用户推荐流。
存储需求:海量、便宜、易用
为什么对象存储为什么需要对象存储呢?
海量数据:抖音每天生成海量的短视频文件。
高性价比:存储系统需要具备高效的数据存储能力,同时成本需控制在合理范围内。
易用性:存储系统需要简单易用,能够高效支持数据上传、下载以及检索等操作。
存储系统:单机存储、单机数据库、分布式数据库、分布式存储
单机存储(单机文件/KV):文件系统、Key-Value 存储
单机数据库(少量(半)结构化数据):关系型数据库、非关系型数据库
分布式数据库(大量(半)结构化数据):关系型数据库、非关系型数据库
分布式存储(大数据计算中间结果/视频/图片):分布式文件系统、对象存储
分布式存储:分布式文件系统HDFS、对象存储TOS
对象存 ...
【青训营X豆包MarsCode】第四课-Redis-大厂程序员是怎么用的
Redis-大厂程序员是怎么用的Redis是什么为什么需要Redis,Redis的基本工作原理
Redis:开源的、高性能的、支持多种数据结构的Key-Value数据库。不仅是一个缓存系统,还是一个持久化的数据库,能够在内存中高效地进行读写操作。
背景:数据量增加、读写数据压力的不断增加(如秒杀、抢购、社交平台的点赞、评论等),传统关系型数据库(如 MySQL)往往无法满足高并发的需求,可能导致响应时间过长、系统崩溃等问题。Redis 的出现提供了一个高效的解决方案。
高性能读写操作: Redis 是一个内存数据库,通过内存存储数据,读取速度极快,尤其在处理大量并发请求时表现优异。
数据持久化:虽然 Redis 是一个内存数据库,但它支持两种持久化机制:RDB 快照和AOF(追加日志)。这使得 Redis 即使在系统重启或故障时,也能恢复数据。
单线程执行:Redis的命令由单一线程处理,避免了多线程带来的复杂性和性能瓶颈。在单线程下实现高并发处理,避免了多线程并发时可能出现的锁竞争、死锁等问题。虽然单线程看似是性能瓶颈,但 Redis 使用了非常高效的事件驱动机制,能够在一个线程内处 ...
【青训营X豆包MarsCode】第三课-带你认识存储 & 数据库
带你认识存储 & 数据库经典案例一条数据从产生,到数据流动,最后持久化的全生命周期
用户脑子 =》 后端服务器 =》 数据库 (《=》其他系统)
数据的持久化
注册“小明”,检查是否存在(合法性),用数据架构组织数据(修改内存),写入硬件(写入存储介质)
潜在问题
Q、数据库怎么保证数据不丢?
数据库通常使用事务日志和多副本存储来保证数据可靠性。即使发生故障,也能通过日志恢复数据。
Q、数据库怎么处理多人同时修改的问题?
数据库通过事务的隔离性和锁机制来确保并发访问的正确性。
Q、为什么用数据库,除了数据库还能存到别的存储系统吗?
数据库提供更强的数据管理能力(如事务、索引、高效查询),但对于特定场景,也可以使用文件系统、分布式存储等替代。
Q、数据库只能处理结构化数据吗?
不是,关系型数据库擅长处理结构化数据,而非关系型数据库可以处理半结构化或非结构化数据(如JSON、图像)。
Q、有哪些操作数据库的方式,要用什么编程语言?
常用SQL操作关系型数据库,或使用数据库的SDK(Java、Python、Go等)与其交互;非关系型数 ...
【青训营X豆包MarsCode】第二课-深入浅出RPC框架
深入浅出 RPC 框架RPC 框架分层设计基本概念RPC (Remote procedure call 远程函数调用)是一种通过网络调用远程服务的方法,使程序可以像调用本地函数一样调用分布式系统中位于远程服务器上的函数。
函数映射、数据转换成字节流、网络传输
函数映射
在客户端调用一个远程函数时,如何将该调用正确映射到服务端对应的函数
服务注册,函数唯一标识符id,接口定义语言(IDL)
本地和远程是不同的进程,不共享内存
数据转换成字节流
将函数的参数和返回值序列化为可以通过网络传输的字节流格式
序列化(Serialization):将参数和返回值转换为字节流。
常用格式:JSON、XML(文本格式,易读但较慢);Protocol Buffers、Thrift、Avro(二进制格式,高效但不易读)。
反序列化(Deserialization):将接收到的字节流还原为原始数据。
序列化工具:
JSON:简单易用,语言无关,但性能不高。
Protocol Buffers(Protobuf):高效二进制序列化,适合高性能 RPC。
Thrift:序列化与 RPC 框架结合,支持多语言 ...
【青训营X豆包MarsCode】第一课-Go 语言基础语法
Go 语言基础语法走进 Go 语言基础语法时间处理时间相关的函数,以及时间的格式化
now := time.Now()fmt.Println(t)fmt.Println(t.Format("2006-01-02 15:04:05"))
数字解析将字符串转成int:strconv.ParseInt(字符串,进制,精度位数) 或者 strconv.Atoi(字符串)(自动识别)
func main() { n, _ := strconv.ParseInt("111", 10, 64) fmt.Println(n) // 111 n2, _ := strconv.Atoi("123") fmt.Println(n2) // 123}
进程信息当我们在命令行中输入 go run example/20-env/main.go a b c d 时,os.Args可以获取到输入的参数 a b c d。
fmt.Println(os.Getenv(“PATH”))打印了环境变量 PATH 的值,它通 ...
Ubuntu双系统安装
Ubuntu双系统安装鉴于Linux在的种种便利,最近打算装一个Ubuntu,虽然之前使用VMware装过Ubuntu的虚拟机,但是由于未知原因(可能是内存不够,同时运行Windows和Ubuntu比较吃力),我的Ubuntu虚拟机运行得比较卡顿,于是想干脆装个双系统好了。
准备材料:U盘(最好8G以上,不要有文件,到时候需要格式化,文件会损坏)
省流:将U盘作为Ubuntu启动盘,在空余的磁盘空间安装Ubuntu系统
安装过程如下
制作启动U盘下载Ubuntu.iso文件
官网:https://ubuntu.com/download/desktop
镜像网:https://mirrors.tuna.tsinghua.edu.cn/ubuntu-releases/
选择合适的版本,注意选择 标记LTS 的版本,表示长期支持(比如24.04,22.04之类的)
下载写入工具(比如rufus、win32diskImager),这里使用win32diskImager
下载地址:https://sourceforge.net/projects/win32diskimager/
选择U盘,写入U ...