二叉树的垂直遍历

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算法,这些天的练习让我对这两种算法有更深的理解。今天的这道题更是让我对前些天的练习有一个综合运用。也让我对之后的算法练习和学习有更大的鼓舞,算法这个东西如果我们能够凭借自己的努力解出来那是相当有成就感的,上次有这种成就感还是大一的时候做高数题。

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

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

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

相关文章

卷积神经网络(CNN)

本文仅在理论方面讲述CNN相关的知识,并给出AlexNet, Agg, ResNet等网络结构的代码。 1.构成 ​ 由输入层、卷积层、池化层、全连接层构成。 输入层:输入数据卷积层:提取图像特征池化层:压缩特征全连接层:为输出准备…

解锁未来:探秘Zxing二维码技术的神奇世界

解锁未来:探秘Zxing二维码技术的神奇世界 1. 引言 在当今数字化和智能化的社会中,二维码技术已经成为人们生活中不可或缺的一部分。从商品购物、支付结算到健康码、门票核销,二维码无处不在,极大地方便了人们的生活和工作。而Zx…

mysq开启慢查询日志,对慢查询进行优化

1.创建实验的环境 创建对应的数据库,然后写脚本向数据库中写入400万条的数据 //创建实验用的数据库 CREATE DATABASE jsschool;//使用当前数据库 USE jsschool;//创建学生表 CREATE TABLE student (sno VARCHAR(20) PRIMARY KEY COMMENT 学生编号,sname VARCHAR(20…

Java 基于springboot+vue的民宿管理系统,附源码

博主介绍:✌程序员徐师兄、7年大厂程序员经历。全网粉丝12w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ 🍅文末获取源码联系🍅 👇🏻 精彩专栏推荐订阅👇…

喝酒到天亮,时刻不敢忘,人间值得——“早”读

春节你小酌了嘛? 引言代码第一篇 人民日报 【夜读】这三句话,致新一年的自己第二篇(跳)李白如何穿越“来”春晚?揭秘→第三篇(跳)人民日报 来啦 新闻早班车要闻社会 政策结尾 引言 完蛋 这个早读…

1. pick gtk dll 程序的制作

文章目录 前言预览细节要点初始窗口尺寸提示音快速提示信息对话框AlertDialog鼠标移入移出事件布局与父子控件关系图片 后续源码及资源 前言 在之前的打包测试中我提到了需要一个挑选dll的程序于是我打算用Gtk来制作这个程序 预览 细节要点 初始窗口尺寸 只有主窗口有set_d…

数学建模:K-means聚类手肘法确定k值(含python实现)

原理 当K-means聚类的k值不被指定时,可以通过手肘法来估计聚类数量。   在聚类的过程中,随着聚类数的增大,样本划分会变得更加精细,每个类别的聚合程度更高,那么误差平方和(SSE)会逐渐变小&am…

【数据存储+多任务爬虫】

数据存储 peewee模块 第三方模块,也需要在cmd中安装。 from peewee import *db MySQLDatabase("spider",host"127.0.0.1",port3306,userroot,password123456 )# 类》表 class Person(Model):name CharField(max_length20) # 类型/约束bi…

基于python深度学习的中文情感分析的系统,附源码

博主介绍:✌程序员徐师兄、7年大厂程序员经历。全网粉丝12W、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ 🍅文末获取源码联系🍅 👇🏻 精彩专栏推荐订阅👇…

利用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文件…

Codeforces Round 113 (Div. 2)E. Tetrahedron(dp、递推)

文章目录 题面链接题意题解代码总结 题面 链接 E. Tetrahedron 题意 从一个顶点出发走过路径长度为n回到出发点的方案总数 题解 考虑dp f [ i ] [ 0 ∣ 1 ∣ 2 ∣ 3 ] f[i][0|1|2|3] f[i][0∣1∣2∣3]:走了i步,现在在j点的方案总数 转移: f [ i ]…

力扣(LeetCode)数据结构练习题

今天来分享两道力扣(LeetCode)的题目来巩固上篇时间复杂度和空间复杂度的知识,也就是在题目上加上了空间复杂度和时间复杂度的限制。 目录 给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素&#xff0c…

ubuntu下如何查看显卡及显卡驱动

ubuntu下如何查看显卡及显卡驱动 使用nvidia-smi 工具查看 查看显卡型号nvida-smi -L $ nvidia-smi -L GPU 0: NVIDIA GeForce RTX 3050 4GB Laptop GPU (UUID: GPU-4cf7b7cb-f103-bf56-2d59-304f8996e28c)当然直接使用nvida-smi 命令可以查看更多信息 $ nvidia-smi Mon Fe…

关于在分布式环境中RVN和使用场景的介绍3

简介 在《关于在分布式环境中RVN和使用场景的介绍2》和《关于在分布式环境中RVN和使用场景的介绍1》中我们介绍了RVN的概念和在一些具体用例中的使用。在本文中我们讨论一下在分布式环境中使用RVN需要注意的问题。 问题 我们在收到一条待处理的事件时,需要检查该…

2024.2.9

作业1 请使用递归实现n&#xff01; #include<stdio.h> #include<string.h> #include<stdlib.h>int fun(int m) {if(m0)return 1;else{return m*fun(m-1);} } int main(int argc, const char *argv[]) {int m;printf("please enter m:");scanf(&…

MySQL 升级脚本制作

当数据库更新字段后或添加一些基础信息&#xff0c;要对生产环境进行升级&#xff0c;之前都是手动编写sql&#xff0c;容易出错还容易缺失。 通过 Navcat 工具的数据库结构同步功能和数据同步功能完成数据库脚本的制作。 一、结构同步功能 1、选择 工具–结构同步&#xff1…

从零开始实现消息队列(一)

从零开始实现消息队列 .什么是消息队列需求分析核心概念模型 . 什么是消息队列 相信大家都了解过阻塞队列和生产者消费者模型,而阻塞队列最大的用途,就是用于实现生产者消费者模型,生产者消费者模型有以下好处: 解耦合 解释: 当主机A给主机B发消息时,A给B发送请求,B给A返回响应…

CTFshow web(php命令执行59-67)

web59 <?php /* # -*- coding: utf-8 -*- # Author: Lazzaro # Date: 2020-09-05 20:49:30 # Last Modified by: h1xa # Last Modified time: 2020-09-07 22:02:47 # email: h1xactfer.com # link: https://ctfer.com */ // 你们在炫技吗&#xff1f; if(isset($_POST…

2024.2.8

1. 现有文件test.c\test1.c\main.c,编写Makkefile Makefile&#xff1a; CCgcc EXEa.out OBJS$(patsubst %.c,%.o,$(wildcard *.c)) CFLAGS-c -oall:$(EXE)$(EXE):$(OBJS)$(CC) $^ -o $%.o:%.c$(CC) $(CFLAGS) $ $^.PHONY:cleanclean:rm $(OBJS) $(EXE) 2. C编程实现&#x…

基于Java (spring-boot)的音乐管理系统

一、项目介绍 播放器的前端&#xff1a; 1.首页&#xff1a;点击歌单中的音乐播放列表中的歌曲进行播放&#xff0c;播放时跳转播放界面&#xff0c;并显示歌手信息&#xff0c;同时会匹配歌词&#xff0c;把相应的歌词显示在歌词面板中。 2.暂停&#xff1a;当歌曲正在播放时…