Leetcode #314:二叉树的竖直遍历

Leetcode #314:二叉树的竖直遍历

题目

题干

该问题二叉树的竖直遍历 题面:

Given a binary tree, return the vertical order traversal of its nodes’ values. (ie, from top to bottom, column by column).

If two nodes are in the same row and column, the order should be from left to right.

给定一个二叉树,返回其结点 垂直方向(从上到下,逐列)遍历的值。
如果两个结点在同一行和列,那么顺序则为 从左到右。

示例

示例1:
输入:[3,9,20,null,null,15,7]
示例1
输出:

[
 [9],
 [3,15],
 [20],
 [7]
]

示例2:
输入: [3,9,8,4,0,1,7]
示例2
输出:

[
 [4],
 [9],
 [3,0,1],
 [8],
 [7]
]

示例3:
输入: [3,9,8,4,0,1,7,null,null,null,2,5]
(0’s right child is 2 and 1’s left child is 5)
示例3
输出:

[
 [4],
 [9,5],
 [3,0,1],
 [8,2],
 [7]
]

题解

竖直遍历二叉树并把每一列存入一个二维数组,示例1中,3和15属于同一列,3在前,示例2中,3,0,1 在同一列,3在前,0和1紧随其后,那么可以感觉到像是一种层序遍历的前后顺序,如何来确定列的顺序呢?可以把根节点给个序号0,然后开始层序遍历,凡是左子节点则序号减1,右子节点序号加1,这样可以通过序号来把相同列的节点值放到一起,用一个TreeMap来建立序号和其对应的节点值的映射,用TreeMap的另一个好处是其自动排序功能可以让列从左到右,由于层序遍历需要用到queue,此时queue 里不能只存节点,而是要存序号和节点组成的pair对儿,这样每次取出就可以操作序号,而且排入队中的节点也赋上其正确的序号。

Python

class BinaryTreeNode(object):
    def __init__(self, data, left=None, right=None):
        self.data = data
        self.left = left
        self.right = right

    def __getitem__(self, key):
        return self.left if key == 0 else self.right

    def __setitem__(self, key, data):
        if (key == 0):
            self.left = data
        elif (key == 1):
            self.right = data

def initTree(elements: list, size: int):
    nodes = []
    for e in elements:
        if e == None:
            nodes.append(None)
        else:
            nodes.append(BinaryTreeNode(e))

    nodelist = [nodes[0]]
    index = 1
    while index < size:
        node = nodelist[0]
        nodelist.pop(0)
        nodelist.append(nodes[index])
        index += 1
        node.left = nodelist[-1]
        nodelist.append(nodes[index])
        index += 1
        node.right = nodelist[-1]
    return nodes[0]

class Solution:
    def __init__(self, root: BinaryTreeNode):
        self.root = root

    def veriticlaTree(self):
        res = []
        if self.root is None:
            return res
        m = {
    
    }
        q = [(0, self.root)]
        while len(q) != 0:
            a = q[0]
            q.pop(0)
            m.setdefault(a[0], []).append(a[1].data)
            if a[1].left:
                q.append((a[0]-1, a[1].left))
            if a[1].right:
                q.append((a[0]+1, a[1].right))
        for _,v in sorted(m.items()):
            res.append(v)
        return res

注意: setdefault()返回的默认空列表是空列表的引用,改变返回的列表值即改变字典的value,并且list.append()操作无返回值,所以第50行如果使用m[a[0]] = m.setdefault(a[0], []).append(a[1].data)则会把None赋值给字典,直接append就行无需赋值。

C++

using namespace std;
#include <iostream>
#include <vector>
#include <map>
#include <queue>

struct TreeNode
{
    
    
    int val;
    TreeNode *left;
    TreeNode *right;
    TreeNode(int x):
        val(x), left(nullptr), right(nullptr) {
    
    }
};

class Solution {
    
    
public:
    vector<vector<int>> verticalOrder(TreeNode* root) {
    
    
        vector<vector<int>> res;
        if (!root) return res;
        map<int, vector<int>> m;
        queue<pair<int, TreeNode*>> q;
        q.push({
    
    0, root});
        while (!q.empty()) {
    
    
            auto a = q.front(); q.pop();
            m[a.first].push_back(a.second->val);
            if (a.second->left) q.push({
    
    a.first - 1, a.second->left});
            if (a.second->right) q.push({
    
    a.first + 1, a.second->right});
        }
        for (auto a : m) {
    
    
            res.push_back(a.second);
        }
        return res;
    }
};

Guess you like

Origin blog.csdn.net/wq_0708/article/details/120089726