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

对位于 (row, col) 的每个结点而言,

其左右子结点分别位于 (row + 1, col - 1) 和 (row + 1, col + 1)

树的根结点位于 (0, 0) 。

二叉树的 垂序遍历 从最左边的列开始直到最右边的列结束,按列索引每一列上的所有结点,

形成一个按出现位置从上到下排序的有序列表。如果同行同列上有多个结点,

则按结点的值从小到大进行排序。

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

输入:root = [3,9,20,null,null,15,7]。

输出:[[9],[3,15],[20],[7]]。

答案2023-06-06:

大体过程如下:

1 定义结构体TreeNode表示二叉树节点,包含属性Val表示节点值和LeftRight分别表示左右节点。

2.定义结构体Info表示节点信息,包含属性rowcolval分别表示节点所在的行、列和值。

3.定义函数NewInfo()创建节点信息。

4.定义切片类型ByColThenRowThenVal并实现其三个方法Len()Less()Swap()使之按列、行和节点值排序。

5.定义函数verticalTraversal()实现二叉树的垂序遍历。

6.在verticalTraversal()中,创建切片collects存储各节点信息,并将根节点的信息存入其中。

7.调用函数dfs()遍历整个二叉树,添加各节点的信息到collects中。

8.对collects按列、行和节点值排序。

9.遍历collects,将同列的所有节点值存入一个新的子切片,将子切片添加到答案ans中。

10.返回答案ans

时间复杂度是O(nlogn),其中n是节点数。n个节点需要遍历一次,排序时间复杂度是O(nlogn)。所以总时间复杂度是O(nlogn)。

空间复杂度是O(n),其中n是节点数。需要使用切片collects来存储节点的信息,collects的长度最大是n,所以空间复杂度是O(n)。

golang完整代码如下:

package main

import (
"fmt"
"sort"
) type TreeNode struct {
Val int
Left *TreeNode
Right *TreeNode
} type Info struct {
row int
col int
val int
} func NewInfo(r, c, v int) Info {
return Info{row: r, col: c, val: v}
} type ByColThenRowThenVal []Info func (bc ByColThenRowThenVal) Len() int { return len(bc) } func (bc ByColThenRowThenVal) Less(i int, j int) bool {
if bc[i].col != bc[j].col {
return bc[i].col < bc[j].col
}
if bc[i].row != bc[j].row {
return bc[i].row < bc[j].row
}
return bc[i].val < bc[j].val
} func (bc ByColThenRowThenVal) Swap(i int, j int) { bc[i], bc[j] = bc[j], bc[i] } func verticalTraversal(root *TreeNode) [][]int {
collects := make([]Info, 0, 1000)
rootInfo := NewInfo(0, 0, root.Val)
collects = append(collects, rootInfo)
dfs(root, rootInfo, &collects)
sort.Sort(ByColThenRowThenVal(collects))
ans := make([][]int, 0, 1000)
for i := 0; i < len(collects); i++ {
if i == 0 || collects[i-1].col != collects[i].col {
ans = append(ans, []int{})
}
ans[len(ans)-1] = append(ans[len(ans)-1], collects[i].val)
}
return ans
} func dfs(root *TreeNode, rootInfo Info, collects *[]Info) {
if root.Left != nil {
leftInfo := NewInfo(rootInfo.row+1, rootInfo.col-1, root.Left.Val)
*collects = append(*collects, leftInfo)
dfs(root.Left, leftInfo, collects)
}
if root.Right != nil {
rightInfo := NewInfo(rootInfo.row+1, rootInfo.col+1, root.Right.Val)
*collects = append(*collects, rightInfo)
dfs(root.Right, rightInfo, collects)
}
} func main() {
leaf7 := &TreeNode{7, nil, nil}
leaf15 := &TreeNode{15, nil, nil}
leaf20 := &TreeNode{20, leaf15, leaf7}
leaf9 := &TreeNode{9, nil, nil}
root := &TreeNode{3, leaf9, leaf20}
result := verticalTraversal(root)
fmt.Println(result)
}

c++完整代码如下:

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std; struct TreeNode {
int val;
TreeNode* left;
TreeNode* right;
TreeNode() : val(0), left(nullptr), right(nullptr) {}
TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
TreeNode(int x, TreeNode* left, TreeNode* right) : val(x), left(left), right(right) {}
}; struct Info {
int row;
int col;
int val;
Info(int r, int c, int v) {
row = r;
col = c;
val = v;
}
}; struct InfoComparator {
bool operator() (const Info& o1, const Info& o2) {
if (o1.col != o2.col) {
return o1.col < o2.col;
}
if (o1.row != o2.row) {
return o1.row < o2.row;
}
return o1.val < o2.val;
}
}; void dfs(TreeNode* root, Info rootInfo, vector<Info>& collects) {
if (root->left != nullptr) {
Info leftInfo(rootInfo.row + 1, rootInfo.col - 1, root->left->val);
collects.push_back(leftInfo);
dfs(root->left, leftInfo, collects);
}
if (root->right != nullptr) {
Info rightInfo(rootInfo.row + 1, rootInfo.col + 1, root->right->val);
collects.push_back(rightInfo);
dfs(root->right, rightInfo, collects);
}
} vector<vector<int>> verticalTraversal(TreeNode* root) {
vector<Info> collects;
Info rootInfo(0, 0, root->val);
collects.push_back(rootInfo);
dfs(root, rootInfo, collects);
sort(collects.begin(), collects.end(), InfoComparator());
vector<vector<int>> ans;
for (int i = 0; i < collects.size(); i++) {
if (i == 0 || collects[i - 1].col != collects[i].col) {
ans.push_back(vector<int>());
}
ans.back().push_back(collects[i].val);
}
return ans;
} int main() {
TreeNode* leaf7 = new TreeNode(7);
TreeNode* leaf15 = new TreeNode(15);
TreeNode* leaf20 = new TreeNode(20, leaf15, leaf7);
TreeNode* leaf9 = new TreeNode(9);
TreeNode* root = new TreeNode(3, leaf9, leaf20);
vector<vector<int>> result = verticalTraversal(root);
for (int i = 0; i < result.size(); i++) {
for (int j = 0; j < result[i].size(); j++) {
cout << result[i][j] << " ";
}
cout << endl;
}
return 0;
}

2023-06-06:给你二叉树的根结点 root ,请你设计算法计算二叉树的 垂序遍历 序列。 对位于 (row, col) 的每个结点而言, 其左右子结点分别位于 (row + 1, col -的更多相关文章

  1. 【2】【leetcode-105,106】 从前序与中序遍历序列构造二叉树,从中序与后序遍历序列构造二叉树

    105. 从前序与中序遍历序列构造二叉树 (没思路,典型记住思路好做) 根据一棵树的前序遍历与中序遍历构造二叉树. 注意:你可以假设树中没有重复的元素. 例如,给出 前序遍历 preorder = [ ...

  2. [Swift]LeetCode987. 二叉树的垂序遍历 | Vertical Order Traversal of a Binary Tree

    Given a binary tree, return the vertical order traversal of its nodes values. For each node at posit ...

  3. [PHP] 算法-根据前序和中序遍历结果重建二叉树的PHP实现

    输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树.假设输入的前序遍历和中序遍历的结果中都不含重复的数字.例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5 ...

  4. 【leetcode 105. 从前序与中序遍历序列构造二叉树】解题报告

    前往 中序,后序遍历构造二叉树, 中序,前序遍历构造二叉树 TreeNode* build(vector<int>& preorder, int l1, int r1, vecto ...

  5. 【leetcode 106. 从中序与后序遍历序列构造二叉树】解题报告

    前往 中序,后序遍历构造二叉树, 中序,前序遍历构造二叉树 TreeNode* build(vector<int>& inorder, int l1, int r1, vector ...

  6. 已知前序(后序)遍历序列和中序遍历序列构建二叉树(Leetcode相关题目)

    1.文字描述: 已知一颗二叉树的前序(后序)遍历序列和中序遍历序列,如何构建这棵二叉树? 以前序为例子: 前序遍历序列:ABCDEF 中序遍历序列:CBDAEF 前序遍历先访问根节点,因此前序遍历序列 ...

  7. leetcode 105 106 从前序与中序遍历序列构造二叉树 从中序与后序遍历序列构造二叉树

    题目: 105 根据一棵树的前序遍历与中序遍历构造二叉树. 注意:你可以假设树中没有重复的元素. 例如,给出 前序遍历 preorder = [3,9,20,15,7] 中序遍历 inorder = ...

  8. LeetCode 中级 - 从前序与中序遍历序列构造二叉树(105)

    一个前序遍历序列和一个中序遍历序列可以确定一颗唯一的二叉树. 根据前序遍历的特点, 知前序序列(PreSequence)的首个元素(PreSequence[0])为二叉树的根(root),  然后在中 ...

  9. 【LeetCode】105#从前序与中序遍历序列构造二叉树

    题目描述 根据一棵树的前序遍历与中序遍历构造二叉树. 注意: 你可以假设树中没有重复的元素. 例如,给出 前序遍历 preorder = [3,9,20,15,7] 中序遍历 inorder = [9 ...

  10. LeetCode 106. 从中序与后序遍历序列构造二叉树(Construct Binary Tree from Inorder and Postorder Traversal)

    题目描述 根据一棵树的中序遍历与后序遍历构造二叉树. 注意:你可以假设树中没有重复的元素. 例如,给出 中序遍历 inorder = [9,3,15,20,7] 后序遍历 postorder = [9 ...

随机推荐

  1. RPC 与 Restful 的区别

    PRC 是一种技术的代名词,HTTP 是一种协议,RPC 可以通过 HTTP 来实现,也可以通过 Socket 自己实现一套协议来实现.所以谈论为什么用 RPC 不用 HTTP 是无意义的.但我们习惯 ...

  2. abp(net core)+easyui+efcore实现仓储管理系统——ABP升级7.3上(五十八)

    Abp(net core)+easyui+efcore实现仓储管理系统目录 abp(net core)+easyui+efcore实现仓储管理系统--ABP总体介绍(一) abp(net core)+ ...

  3. 二进制安装Kubernetes(k8s) v1.23.7 IPv4/IPv6双栈

    二进制安装Kubernetes(k8s) v1.23.7 IPv4/IPv6双栈 Kubernetes 开源不易,帮忙点个star,谢谢了 介绍 kubernetes二进制安装 后续尽可能第一时间更新 ...

  4. flak_login用法

    基础的信息和全局配置这里就不多说,需要用到再斟酌也可以的.这里也是针对每个模块较为常用的进行解释说明,后期再使用过程中遇到会进行补充. Login_Manager LoginManager是一个类,有 ...

  5. Terraform 系列-Terraform 简介

    系列文章 Terraform 系列文章 前言 最近在使用 Terraform 来置备 OCI 的 Always Free Tier, 发现它非常好用.总结学习下:Terraform 的基础知识. 什么 ...

  6. 【Dotnet 工具箱】WPF UI - 现代化设计的开源 WPF 框架

    1.WPF UI - 现代化设计的开源 WPF 框架 WPF UI 是一个基于 C# 开发的, 拥有 4k star 的开源 UI 框架.WPF UI 在 WPF 的基础上,提供了更多的现代化,流利的 ...

  7. Nginx的负载均衡策略

    Nginx的负载均衡策略 个人博客地址: https://note.raokun.top 拥抱ChatGPT,国内访问网站:https://www.playchat.top 共六种: 轮询.权重.ip ...

  8. 学习MASA第一天:MASA Blazor TEST项目创建

    个人博客地址: https://note.raokun.top 拥抱ChatGPT,国内访问网站:https://www.playchat.top 学习MASA第一天:MASA Blazor TEST ...

  9. [Pytorch框架] 1.6 训练一个分类器

    文章目录 训练一个分类器 关于数据? 训练一个图像分类器 在GPU上训练 多GPU训练 下一步? 训练一个分类器 上一讲中已经看到如何去定义一个神经网络,计算损失值和更新网络的权重. 你现在可能在想下 ...

  10. Python-获取Local Storage和Session Storage

    一.简介 LocalStorage 是只读的.数据存储也是跨浏览器会话.LocalStorage 类似于SessionStorage. 区别在于,数据存储在 LocalStorage 是无期限的,而当 ...