1.1. 题目

1.1.1. 二叉树的垂序遍历

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

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

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

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

示例 1:

示例 1

输入:root = [3,9,20,null,null,15,7]
输出:[[9],[3,15],[20],[7]]
解释:
列 -1 :只有结点 9 在此列中。
列  0 :只有结点 3 和 15 在此列中,按从上到下顺序。
列  1 :只有结点 20 在此列中。
列  2 :只有结点 7 在此列中。

示例 2:

示例 2

输入:root = [1,2,3,4,5,6,7]
输出:[[4],[2],[1,5,6],[3],[7]]
解释:
列 -2 :只有结点 4 在此列中。
列 -1 :只有结点 2 在此列中。
列  0 :结点 1 、5 和 6 都在此列中。
          1 在上面,所以它出现在前面。
          5 和 6 位置都是 (2, 0) ,所以按值从小到大排序,5 在 6 的前面。
列  1 :只有结点 3 在此列中。
列  2 :只有结点 7 在此列中。

示例 3:

示例 3

输入:root = [1,2,3,4,6,5,7]
输出:[[4],[2],[1,5,6],[3],[7]]
解释:
这个示例实际上与示例 2 完全相同,只是结点 5 和 6 在树中的位置发生了交换。
因为 5 和 6 的位置仍然相同,所以答案保持不变,仍然按值从小到大排序。



1.1.2. 题解:

  • 这题看起来简单,其实容易出坑,我一开始就没有注意到 它相同列里 要根据层来排序....
  • 这题简单理解,就是不要看题目的"坐标",就理解成每个节点 有个 值, 比如根节点开始, 根节点是0, 它的左子节点是 -1,右子节点是1, 根节点的左子节点的左子节点是 -2,依次类推
  • 然后注意一下示例的2和3, 如果是同一高度的同一个 "横坐标",需要进行大小排序,这里注意,不是全部排序,是同一层的同一个 横坐标需要排序

1.1.3. 思路:

  • 首先,肯定是 从根节点开始递归,可以中序遍历树, 左节点就减一,右节点就加一
  • 然后有个map,记录每层的每个横坐标里的值, 公式 map[层][横坐标的值] = []int{这一层里相同横坐标的节点的值}
  • 比如 根节点所在的 0层, map[0][0] = []int{0},
  • 比如根节点的左右子节点, 左节点: map[1][-1] = []int{-1}, 右节点: map[1][1] = []int{1}
  • 然后把一层里的值进行排序

1.1.4. 代码:

点击显示
 func verticalTraversal(root *TreeNode) (res [][]int) {
    if root == nil {
        return nil
    }
    // 一个map,存 每层对应相同横坐标的 集合
    mn := make(map[int]map[int][]int)

    // 匿名函数 遍历二叉树, n是横坐标的值, deep是树高
    var f func(t *TreeNode, n, deep int)

    // min,max 是 横坐标的最大最小值, deepMax是树最高
    var min, max, deepMax int

    f = func(t *TreeNode, n, deep int) {
        if t == nil {
            return
        }
        // 记录 横坐标的最大最小值
        if n > max {
            max = n
        }

        if n < min {
            min = n
        }
        // 记录 树高最大值
        if deep > deepMax {
            deepMax = deep
        }

        // 如果是新遍历到这层,需要重新定义一个map
        if _, ok := mn[deep]; !ok {
            m := make(map[int][]int)
            m[n] = append(m[n], t.Val)
            mn[deep] = m

        } else {
            // 把值插入到 同一层的同一个横坐标的里面

            mn[deep][n] = append(mn[deep][n], t.Val)

            // 我下面自己写了一个排序,也可以用go自带的sort排序,自带的是 快排

            //if len(mn[deep][n]) == 0 {
            //    mn[deep][n] = append(mn[deep][n], t.Val)
            //
            //} else {
            //    mn[deep][n] = sort(mn[deep][n], t.Val)
            //}
            sort2.Ints(mn[deep][n])

        }

        deep++
        f(t.Left, n-1, deep)
        f(t.Right, n+1, deep)
    }
    f(root, 0, 0)

    //fmt.Println("====================")
    //fmt.Println(min, max, deepMax)

    temp := make(map[int][]int)

    // 把不同层里的相同横坐标进行合并
    for i := 0; i <= deepMax; i++ {
        for j := min; j <= max; j++ {
            temp[j] = append(temp[j], mn[i][j]...)
        }
    }

    // 我测试看结果的
    for k, v := range temp {
        fmt.Println(k, v)
    }

    // 把结果输出出去
    for i := min; i <= max; i++ {
        res = append(res, temp[i])
    }

    return res
}

// 自己实现的排序,本来想用二分进行插入,发现条件太多,就改用这种简单冒泡方式了
func sort(arr []int, n int) (res []int) {
    //fmt.Println(arr, n)
    if len(arr) == 1 {
        if arr[0] > n {
            res = []int{n, arr[0]}
        } else {
            res = []int{arr[0], n}
        }
        return
    }

    if n <= arr[0] {
        res = append([]int{n}, arr...)
        return
    }

    if n >= arr[len(arr)-1] {
        res = append(res, n)
    }

    for i := 0; i < len(arr); i++ {
        if n >= arr[i] && n <= arr[i+1] {
            res = append(res, arr[:i+1]...)
            res = append(res, n)
            res = append(res, arr[i+1:]...)
            break
        }
    }
    return
}

代码

results matching ""

    No results matching ""