编程题目:
给你二叉树的根结点 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;
}
};