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完整代码如下:

  1. package main
  2. import (
  3. "fmt"
  4. "sort"
  5. )
  6. type TreeNode struct {
  7. Val int
  8. Left *TreeNode
  9. Right *TreeNode
  10. }
  11. type Info struct {
  12. row int
  13. col int
  14. val int
  15. }
  16. func NewInfo(r, c, v int) Info {
  17. return Info{row: r, col: c, val: v}
  18. }
  19. type ByColThenRowThenVal []Info
  20. func (bc ByColThenRowThenVal) Len() int { return len(bc) }
  21. func (bc ByColThenRowThenVal) Less(i int, j int) bool {
  22. if bc[i].col != bc[j].col {
  23. return bc[i].col < bc[j].col
  24. }
  25. if bc[i].row != bc[j].row {
  26. return bc[i].row < bc[j].row
  27. }
  28. return bc[i].val < bc[j].val
  29. }
  30. func (bc ByColThenRowThenVal) Swap(i int, j int) { bc[i], bc[j] = bc[j], bc[i] }
  31. func verticalTraversal(root *TreeNode) [][]int {
  32. collects := make([]Info, 0, 1000)
  33. rootInfo := NewInfo(0, 0, root.Val)
  34. collects = append(collects, rootInfo)
  35. dfs(root, rootInfo, &collects)
  36. sort.Sort(ByColThenRowThenVal(collects))
  37. ans := make([][]int, 0, 1000)
  38. for i := 0; i < len(collects); i++ {
  39. if i == 0 || collects[i-1].col != collects[i].col {
  40. ans = append(ans, []int{})
  41. }
  42. ans[len(ans)-1] = append(ans[len(ans)-1], collects[i].val)
  43. }
  44. return ans
  45. }
  46. func dfs(root *TreeNode, rootInfo Info, collects *[]Info) {
  47. if root.Left != nil {
  48. leftInfo := NewInfo(rootInfo.row+1, rootInfo.col-1, root.Left.Val)
  49. *collects = append(*collects, leftInfo)
  50. dfs(root.Left, leftInfo, collects)
  51. }
  52. if root.Right != nil {
  53. rightInfo := NewInfo(rootInfo.row+1, rootInfo.col+1, root.Right.Val)
  54. *collects = append(*collects, rightInfo)
  55. dfs(root.Right, rightInfo, collects)
  56. }
  57. }
  58. func main() {
  59. leaf7 := &TreeNode{7, nil, nil}
  60. leaf15 := &TreeNode{15, nil, nil}
  61. leaf20 := &TreeNode{20, leaf15, leaf7}
  62. leaf9 := &TreeNode{9, nil, nil}
  63. root := &TreeNode{3, leaf9, leaf20}
  64. result := verticalTraversal(root)
  65. fmt.Println(result)
  66. }

c++完整代码如下:

  1. #include <iostream>
  2. #include <vector>
  3. #include <algorithm>
  4. using namespace std;
  5. struct TreeNode {
  6. int val;
  7. TreeNode* left;
  8. TreeNode* right;
  9. TreeNode() : val(0), left(nullptr), right(nullptr) {}
  10. TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
  11. TreeNode(int x, TreeNode* left, TreeNode* right) : val(x), left(left), right(right) {}
  12. };
  13. struct Info {
  14. int row;
  15. int col;
  16. int val;
  17. Info(int r, int c, int v) {
  18. row = r;
  19. col = c;
  20. val = v;
  21. }
  22. };
  23. struct InfoComparator {
  24. bool operator() (const Info& o1, const Info& o2) {
  25. if (o1.col != o2.col) {
  26. return o1.col < o2.col;
  27. }
  28. if (o1.row != o2.row) {
  29. return o1.row < o2.row;
  30. }
  31. return o1.val < o2.val;
  32. }
  33. };
  34. void dfs(TreeNode* root, Info rootInfo, vector<Info>& collects) {
  35. if (root->left != nullptr) {
  36. Info leftInfo(rootInfo.row + 1, rootInfo.col - 1, root->left->val);
  37. collects.push_back(leftInfo);
  38. dfs(root->left, leftInfo, collects);
  39. }
  40. if (root->right != nullptr) {
  41. Info rightInfo(rootInfo.row + 1, rootInfo.col + 1, root->right->val);
  42. collects.push_back(rightInfo);
  43. dfs(root->right, rightInfo, collects);
  44. }
  45. }
  46. vector<vector<int>> verticalTraversal(TreeNode* root) {
  47. vector<Info> collects;
  48. Info rootInfo(0, 0, root->val);
  49. collects.push_back(rootInfo);
  50. dfs(root, rootInfo, collects);
  51. sort(collects.begin(), collects.end(), InfoComparator());
  52. vector<vector<int>> ans;
  53. for (int i = 0; i < collects.size(); i++) {
  54. if (i == 0 || collects[i - 1].col != collects[i].col) {
  55. ans.push_back(vector<int>());
  56. }
  57. ans.back().push_back(collects[i].val);
  58. }
  59. return ans;
  60. }
  61. int main() {
  62. TreeNode* leaf7 = new TreeNode(7);
  63. TreeNode* leaf15 = new TreeNode(15);
  64. TreeNode* leaf20 = new TreeNode(20, leaf15, leaf7);
  65. TreeNode* leaf9 = new TreeNode(9);
  66. TreeNode* root = new TreeNode(3, leaf9, leaf20);
  67. vector<vector<int>> result = verticalTraversal(root);
  68. for (int i = 0; i < result.size(); i++) {
  69. for (int j = 0; j < result[i].size(); j++) {
  70. cout << result[i][j] << " ";
  71. }
  72. cout << endl;
  73. }
  74. return 0;
  75. }

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. Mysql 事务隔离级别和锁的关系

    我们都知道事务的几种性质,数据库为了维护这些性质,尤其是一致性和隔离性,一般使用加锁这种方式.同时数据库又是个高并发的应用,同一时间会有大量的并发访问,如果加锁过度,会极大的降低并发处理能力.所以对于 ...

  2. HashMap和ConcurrentHashMap扩容过程

    HashMap 存储结构 HashMap是数组+链表+红黑树(1.8)实现的. (1)Node[] table,即哈希桶数组.Node是内部类,实现了Map.Entry接口,本质是键值对. 下图链表中 ...

  3. 购物车,实现增删改查;无bug,还有一个直接修改购物车数量功能未实现

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  4. Linux中Python自动输入sudo 密码【管道 sudo参数 stdin&stdout】

    一.背景和需求 背景: 由于docker服务进程都是以root帐号的身份运行的,所以用docker跑abpred出来的文件所有者都是root, 而我作为一般用户,操作这个文件不够权限,运行代码时需要s ...

  5. 关于java.lang.Object类、equals()、toString()的使用、以及方法得重载和重写得一些笔记

    java.lang.Object类 * 1.Object类是所有Java类的根父类; * 2.如果在类的声明中未使用extends关键字指明其父类,则默认父类为java.lang.Object类 * ...

  6. [Java SE]javac编译时编码错误

    1 问题复现 Information:java: javacTask: 源发行版 8 需要目标发行版 1.8 Information:java: Errors occurred while compi ...

  7. [数据库]MySQL之备份与恢复【未完待续】

    1 恢复 方式一 source sqlFile.sql 登陆MySQL 创建数据库db (create database db;) 进入/使用 数据库db (use db;) 将要导入的sql文件放到 ...

  8. 在IIS 搭建FTP站点

    最近在项目中需要用到FTP,需要将生成的文件通过FTP上传网站. 在此记录下. FTP SSL设置,需要允许SSL连接. FTP 身份验证,匿名身份验证需要启用. FTP 授权规则,如果没有特殊情况允 ...

  9. Vite-Admin后台管理系统|vite4+vue3+pinia前端后台框架实例

    基于vite4.x+vue3+pinia前端后台管理系统解决方案ViteAdmin. 前段时间分享了一篇vue3自研pc端UI组件库VEPlus.这次带来最新开发的基于vite4+vue3+pinia ...

  10. 【SSM项目】尚筹网(三)基于Servlet3.0项目搭建:异常映射和拦截器机制

    1 异常映射 1.1 目标 使用异常映射对项目的异常和错误提示进行统一管理. 1.2 思路 对于普通的页面请求,异常映射机制捕获到handler方法抛出的异常后会响应为一个错误页面,对于处理ajax请 ...