二叉树的垂直遍历

1.题目

这道题是2024-2-13的签到题,题目难度为困难。

考察的知识点是DFS算法和自定义排序。

题目链接:二叉树的垂直遍历

给你二叉树的根结点 root ,请你设计算法计算二叉树的 垂序遍历 序列。

对位于 (row, col) 的每个结点而言,其左右子结点分别位于 (row + 1, col - 1) 和 (row + 1, col + 1) 。树的根结点位于 (0, 0) 。

二叉树的 垂序遍历 从最左边的列开始直到最右边的列结束,按列索引每一列上的所有结点,形成一个按出现位置从上到下排序的有序列表。如果同行同列上有多个结点,则按结点的值从小到大进行排序。

返回二叉树的 垂序遍历 序列。

2.思路

说实话,之前碰到的困难题目大部分我都是直接放弃的,但是通过这段时间对DFS算法的使用后我尝试独立解决这道题,发现还是可以解出来的。这道题其实有两大难点:

  1. 如何得到所有列的所有结点
  2. 如何让每列的结点按照题目要求排序

下面是我对这道题的所有思路:

初步思路——如何理解坐标

对于题目中的要求,根节点的坐标为(0,0),其它坐标都符合以下规律:

对于所有的左子结点,它的坐标为(x_parent+1,y_parent-1)。

对于所有的右子结点,它的坐标为(x_parent+1,y_parent+1)。

其中x_parent是这些节点的父节点x坐标值,y_parent是这些结点的父节点y坐标值。

选择什么算法来解题——DFS算法

其实刚开始我是打算用BFS算法来解题的,因为根据这道题的结果来看,它里面的列表结果值是根据结点的x坐标排序的,但如果使用BFS算法有一个问题,就是我如何在BFS遍历过程中读取父节点的坐标呢?因为这个坐标是我们自己定义的,并不是TreeNode自带的属性。因此我想到了使用DFS遍历。

对于DFS遍历,它一般都是用递归的方式来写的,因此我可以给递归函数加上两个参数用来传入父节点的x坐标和y坐标。同时我们根据前面的坐标规律来进行子结点遍历。对于每个结点,我们利用一个结构来存储它们的信息——字典(哈希表)。这样我们就可以把每个列的所有结点信息保留。

怎么按照题目要求排序?

在完成DFS遍历所有节点后我们能够得到所有列的所有结点,但这就完事了吗?它还有一个难点,我们还需要进行排序,因此我们得弄清楚题目的排序要求:

  1. 根据列的值来排序(升序)
  2. 根据行的值来排序(升序)
  3. 根据结点的值排序(升序)

由于我比较喜欢用python来写算法题目,因此这里我借助python的sorted函数、lambda表达式等python内置语法来写一些排序规则,下面是我的排序整体思路:

首先我们用字典的内置函数items()函数来获取一个迭代器对象,并将这个迭代器传入到sorted函数里面(进行排序),排序规则按照字典的键来升序排序。

将前面得到的迭代器对象根据结点的列排序后,我们还需要根据后面两个排序规则排序,这里我们利用python的for循环来获取前面的迭代器对象元素,同时我们还要借助元组的拆包语法来获取对应的两个子元素:sk,val。

我们需要对val进行自定义排序,排序规则根据每个元素的行和值进行排序。最后我们利用列表表达式来得到每一列的所有节点值,并存入到结果列表中。

最后我们直接返回结果列表就行了。

3.代码

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:def verticalTraversal(self, root: Optional[TreeNode]) -> List[List[int]]:# 定义一个字典,用来存储每一列的结点信息rst = {}# 定义DFS函数,这里是前序遍历def dfs(node,x,y):# 如果结点存在的话if node:# 如果rst里面没有第y列的话,则初始化第y列的列表信息# 其中,x是当前结点的行,node.val是当前结点的值if y not in rst:rst[y] = [(x,node.val)]# 如果rst里面有第y列的话,则添加第y列的列表信息else:rst[y].append((x,node.val))# 剪枝操作,如果当前结点存在左子结点if node.left:dfs(node.left,x+1,y-1)# 剪枝操作,如果当前结点存在右子结点if node.right:dfs(node.right,x+1,y+1)# DFS遍历root结点dfs(root,0,0)# 获取前面的字典迭代器对象(排序后的)# 根据列来排序sort_key = sorted(rst.items(),key=lambda x:x[0])# 保存最终结果ans = []# 利用拆包和循环遍历前面的迭代器对象for sk,val in sort_key:# 将每列的结点信息按照行和它的值来排序val = sorted(val,key=lambda x:[x[0],x[1]])# 利用列表推导式来获取最终的格式结果tmp = [v[1] for v in val]# 添加到结果列表里面ans.append(tmp)return ans

4.总结

        今天的这道签到题是今年(2024)我第一道有成就感的题目,毕竟是今年第一道自己独立解决的困难题。过年的这几天签到题都是DFS算法或BFS算法,这些天的练习让我对这两种算法有更深的理解。今天的这道题更是让我对前些天的练习有一个综合运用。也让我对之后的算法练习和学习有更大的鼓舞,算法这个东西如果我们能够凭借自己的努力解出来那是相当有成就感的,上次有这种成就感还是大一的时候做高数题。

总而言之,算法思维并不是天生就有的,我也并不是天赋很好的选手,只能凭借每天的算法练习来学习和掌握常见的算法题。俗话说一个人走的更快,一群人走的更远。这段时间的算法练习中,我将自己每天的算法思路分享给大家参考,这不仅是让我对这道题进一步的分析,也能够给大家一点参考,最后祝大家新年快乐!。

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

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

相关文章

VTK 正交投影 透视投影

1.VTK默认透视投影(近大远小); 1.调用vtkCamera的ParallelProjectionOn函数开启 2.通过vtkCamera的SetParallelScale缩放 3.通过vtkCamera的SetClippingRange设置前后裁剪平面 2.正交投影(平行投影,远近一样&#xf…

openGauss学习笔记-218 openGauss性能调优-确定性能调优范围-硬件瓶颈点分析-I/O

文章目录 openGauss学习笔记-218 openGauss性能调优-确定性能调优范围-硬件瓶颈点分析-I/O218.1 查看I/O状况218.2 性能参数分析 openGauss学习笔记-218 openGauss性能调优-确定性能调优范围-硬件瓶颈点分析-I/O 获取openGauss节点的CPU、内存、I/O和网络资源使用情况&#xf…

LeetCode:83和82.删除排序链表中的重复元素I,II

这两题算是链表的基础题,就遍历删除没啥特点, 83甚至不需要考虑第一个结点的特殊情况,属实是名副其实的easy了 LeetCode:21.合并两个有序链表之第一次的特殊情况-CSDN博客 83. 删除排序链表中的重复元素 - 力扣(Lee…

第三百二十二回

文章目录 1. 概念介绍2. 使用方法2.1 基本用法2.2 缓冲原理 3. 示例代码4. 内容总结 我们在上一章回中介绍了"FadeInImage组件"相关的内容,本章回中将介绍CachedNetworkImage组件.闲话休提,让我们一起Talk Flutter吧。 1. 概念介绍 我们在本章…

渗透测试练习题解析 3(CTF web)

1、[网鼎杯 2020 朱雀组]phpweb 1 考点:反序列化漏洞利用 进入靶场,查看检查信息,发现存在两个参数 func 和 p 查看页面源代码 payload:funcfile_get_contents&pphp://filter/resourceindex.php 整理后,就是 PHP 代…

HiveSQL——连续增长问题

注:参考文章: SQL连续增长问题--HQL面试题35_sql判断一个列是否连续增长-CSDN博客文章浏览阅读2.6k次,点赞6次,收藏30次。目录0 需求分析1 数据准备3 小结0 需求分析假设我们有一张订单表shop_order shop_id,order_id,order_time…

基于Java (spring-boot)的职工管理系统

一、项目介绍 基于Java (spring-boot)的职工管理系统功能:登录、老板、职员人事经理、职员、部门列表、职工列表、权限修改、查看所有管理、正在审核列表、添加考勤、添加职工、添加奖惩、合同列表、合同信息、等等等。 适用人群:适合小白、大学生、毕业…

【Java八股面试系列】JVM-类和对象加载过程

目录 类和对象的加载过程 类的生命周期 类的加载过程 加载 验证 准备 解析 初始化 类卸载 对象的加载过程 类和对象的加载过程 什么是类加载和对象加载? 类加载(Class Loading):这是指JVM在运行时将类的字节码文件加载到内存中的…

利用pandas库进行数据分析

一.这段代码的主要目的是读取IMDB电影数据集,并进行一些基本的数据分析 # codingutf-8 import pandas as pd import numpy as np from matplotlib import pyplot as plt# 定义CSV文件的路径 file_path ./IMDB-Movie-Data.csv# 使用pandas的read_csv函数读取CSV文件…

海量数据处理商用短链接生成器平台 - 3

第三章 商用短链平台实战-账号微服务流量包设计 第1集 账号微服务和流量包数据库表索引规范讲解 简介:账号微服务和流量包数据库表索引规范讲解 索引规范 主键索引名为 pk_字段名; pk即 primary key;唯一索引名为 uk_字段名;uk 即 unique key普通索引…

力扣题目训练(9)

2024年2月2日力扣题目训练 2024年2月2日力扣题目训练412. Fizz Buzz414. 第三大的数415. 字符串相加129. 求根节点到叶节点数字之和131. 分割回文串65. 有效数字 2024年2月2日力扣题目训练 2024年2月2日第九天编程训练,今天主要是进行一些题训练,包括简…

[BJDCTF2020]ZJCTF,不过如此

伪协议读取next.php源码 preg_replace() /e代码执行漏洞_preg_replace /e-CSDN博客 查找资料我们发现,在php5.6及以下版本中,/e使得preg_replace的第二个参数可以被当作php代码执行,第二个参数中\\1指的是正则匹配到的第一组文本&#xff0c…