987. 二叉树的垂序遍历
难度 : 困难
题目大意:
给你二叉树的根结点
root
,请你设计算法计算二叉树的 垂序遍历 序列。对位于
(row, col)
的每个结点而言,其左右子结点分别位于(row + 1, col - 1)
和(row + 1, col + 1)
。树的根结点位于(0, 0)
。二叉树的 垂序遍历 从最左边的列开始直到最右边的列结束,按列索引每一列上的所有结点,形成一个按出现位置从上到下排序的有序列表。如果同行同列上有多个结点,则按结点的值从小到大进行排序。
返回二叉树的 垂序遍历 序列。
提示:
- 树中结点数目总数在范围
[1, 1000]
内0 <= Node.val <= 1000
示例 1:
输入:root = [3,9,20,null,null,15,7] 输出:[[9],[3,15],[20],[7]] 解释: 列 -1 :只有结点 9 在此列中。 列 0 :只有结点 3 和 15 在此列中,按从上到下顺序。 列 1 :只有结点 20 在此列中。 列 2 :只有结点 7 在此列中。
思路
根据题目的意思,我们只需要将所有的信息存下来,最后排序即可,然后将所有的数据分组,返回答案即可,我们要记录3个数据,每个节点的{深度, 编号, 值}
,因为超过了两个数据,我们不能用pair<int, int>
,我们可以使用元组,tuple<int, int, int>
,最后分组一下即可
dfs
/**
* 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:
using TIII = tuple<int, int, int>;
vector<vector<int>> verticalTraversal(TreeNode* root) {
vector<TIII> pos;
function<void(TreeNode*, int, int)> dfs = [&](TreeNode* u, int dep, int id) -> void {
pos.push_back({id, dep, u->val});
if (u->left) dfs(u->left, dep + 1, id - 1);
if (u->right) dfs(u->right, dep + 1, id + 1);
};
dfs(root, 0, 0);
sort(pos.begin(), pos.end(), [&](TIII& a, TIII& b) {
if (get<0>(a) != get<0>(b)) return get<0>(a) < get<0>(b);
else if (get<1>(a) != get<1>(b)) return get<1>(a) < get<1>(b);
return get<2>(a) < get<2>(b);
});
vector<vector<int>> res;
for (int i = 0; i < pos.size(); ) {
vector<int> t;
int j = get<0>(pos[i]), k = i;
// 分组
while (k < pos.size() && get<0>(pos[k]) == j) {
t.push_back(get<2>(pos[k ++]));
}
res.push_back(t);
i = k;
}
return res;
}
};
时间复杂度 : O ( n ) O(n) O(n)
结束了