编程训练第八十六期——二叉树的垂序遍历

编程题目:

给你二叉树的根结点 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]]

  • 输入:root = [1,2,3,4,5,6,7]
    输出:[[4],[2],[1,5,6],[3],[7]]

  • 输入:root = [1,2,3,4,6,5,7]
    输出:[[4],[2],[1,5,6],[3],[7]]


解法:

1.bfs+排序
首先通过层次遍历(借助队列)来获得每个结点的坐标,再利用sort进行排序。注意此时需要自定义排序函数,规则是1)当行和列都相同时,按照结点值的由小到大排序;2)当行不同,列相同时,按照行由小到大排序;3)当行和列都不同时,按照列进行排序。最后通过一次循环遍历,即可得到答案。
时间复杂度O(NlogN)
空间复杂度O(N)

/**
 * Definition for a binary tree node.
 * 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) {}
 * };
 */
class Solution {
public:
    vector<vector<int>> pos;
    void bfs(TreeNode *root)
    {
        queue<TreeNode *> queNode;
        queue<vector<int>> quePos;
        queNode.push(root);
        quePos.push({0, 0});
        while (!queNode.empty())
        {
            int size = queNode.size();
            for (int i = 0; i < size; i++)
            {
                TreeNode *cur = queNode.front();
                int row = quePos.front()[0];
                int col = quePos.front()[1];
                queNode.pop();
                quePos.pop();
                pos.push_back({cur->val, row, col});
                if (cur->left)
                {
                    queNode.push(cur->left);
                    quePos.push({row + 1, col - 1});
                }

                if (cur->right)
                {
                    queNode.push(cur->right);
                    quePos.push({row + 1, col + 1});
                }
            }
        }
    }

    static bool compare(const vector<int> a, const vector<int> b)
    {
        if (a[1] == b[1] && a[2] == b[2])
            return a[0] < b[0];
        
        if (a[2] == b[2])
            return a[1] < b[1];

        return a[2] < b[2];
    }

    vector<vector<int>> verticalTraversal(TreeNode* root) {
        bfs(root);
        sort(pos.begin(), pos.end(), compare);
        vector<vector<int>> res;
        res.push_back({pos[0][0]});
        int index = 0;
        for (int i = 1; i < pos.size(); i++)
        {
            if (pos[i][2] == pos[i - 1][2])
                res[index].push_back(pos[i][0]);
            else
            {
                res.push_back({pos[i][0]});
                index++;
            }
                
        }
        return res;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值