把二叉树放到坐标网格上看看,以根节点为原点,往左的节点 x--
,往右的节点 x++
,往下的节点 y--
。
https://camo.githubusercontent.com/36c0d85d07b7b9028cf20c19b87e242ea0e37216e9453e4bb5cfe0c965e48b1b/68747470733a2f2f63646e2e6a7364656c6976722e6e65742f67682f7375756b69692f39312d646179732d616c676f726974686d2f6173736574732f3938375f302e706e67
x
坐标分组,然后按 x
升序排序。x
坐标分组内,把节点按 y
坐标降序排序,如果 y
坐标相同,再按节点值升序排序。/**
* 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>> verticalTraversal(TreeNode* root) {
vector<tuple<int, int, int>> nodes;
function<void(TreeNode* root, int x, int y)> dfs = [&](TreeNode* root, int x, int y) {
if (root == nullptr) return;
nodes.emplace_back(x, y, root->val);
dfs(root->left, x - 1, y + 1);
dfs(root->right, x + 1, y + 1);
};
dfs(root, 0, 0);
sort(nodes.begin(), nodes.end());
vector<vector<int>> ans;
int curX = INT_MIN;
for (const auto& [x, y, val] : nodes) {
if (x > curX) {
curX = x;
ans.emplace_back();
}
ans.back().push_back(val);
}
return ans;
}
};
/**
* Definition for a binary tree node.
* function TreeNode(val) {
* this.val = val;
* this.left = this.right = null;
* }
*/
/**
* @param {TreeNode} root
* @return {number[][]}
*/
var verticalTraversal = function (root) {
if (!root) return [];
// 坐标集合以 x 坐标分组
const pos = {};
// dfs 遍历节点并记录每个节点的坐标
dfs(root, 0, 0);
// 得到所有节点坐标后,先按 x 坐标升序排序
let sorted = Object.keys(pos)
.sort((a, b) => +a - +b)
.map(key => pos[key]);
// 再给 x 坐标相同的每组节点坐标分别排序
sorted = sorted.map(g => {
g.sort((a, b) => {
// y 坐标相同的,按节点值升序排
if (a[0] === b[0]) return a[1] - b[1];
// 否则,按 y 坐标降序排
else return b[0] - a[0];
});
// 把 y 坐标去掉,返回节点值
return g.map(el => el[1]);
});
return sorted;
// *********************************
function dfs(root, x, y) {
if (!root) return;
x in pos || (pos[x] = []);
// 保存坐标数据,格式是: [y, val]
pos[x].push([y, root.val]);
dfs(root.left, x - 1, y - 1);
dfs(root.right, x + 1, y - 1);
}
};
/**
* Definition for a binary tree node.
* function TreeNode(val) {
* this.val = val;
* this.left = this.right = null;
* }
*/
/**
* @param {TreeNode} root
* @return {number[][]}
*/
var verticalTraversal = function (root) {
if (!root) return [];
// 坐标集合以 x 坐标分组
const pos = bfs(root);
// 得到所有节点坐标后,先按 x 坐标升序排序
let sorted = Object.keys(pos)
.sort((a, b) => +a - +b)
.map(key => pos[key]);
// 再给 x 坐标相同的每组节点坐标分别排序
sorted = sorted.map(g => {
g.sort((a, b) => {
// y 坐标相同的,按节点值升序排
if (a[0] === b[0]) return a[1] - b[1];
// 否则,按 y 坐标降序排
else return b[0] - a[0];
});
// 把 y 坐标去掉,返回节点值
return g.map(el => el[1]);
});
return sorted;
// *********************************
function bfs(root) {
// 队列中数据格式是: [x, y, val]
const queue = [[0, 0, root]];
const pos = {};
while (queue.length) {
let size = queue.length;
while (size--) {
const [x, y, node] = queue.shift();
x in pos || (pos[x] = []);
// 保存坐标数据到 pos,格式是: [y, val]
pos[x].push([y, node.val]);
node.left && queue.push([x - 1, y - 1, node.left]);
node.right && queue.push([x + 1, y - 1, node.right]);
}
}
return pos;
}
};