Open threedayAAAAA opened 1 year ago
dfs,每次都将当前节点的垂系坐标以及深度进行记录,最后排序下即可
function verticalTraversal(root: TreeNode | null): number[][] {
const orderDataMap: Record<string, Record<string, number[]>> = {}
function help(node: TreeNode | null, cur: number, dep: number){
if(!node) return
const orderData = orderDataMap[cur] ?? {}
const depData = orderData[dep] ?? []
depData.push(node.val)
orderData[dep] = depData
orderDataMap[cur] = orderData
node.left && help(node.left, cur - 1, dep + 1)
node.right && help(node.right, cur + 1, dep + 1)
}
help(root, 0, 0)
return orderMapDataByKey(orderDataMap).map(item => {
return orderMapDataByKey(item)
.reduce((pre, item) => pre.concat(item.sort((a, b) => a - b)), [])
})
};
function orderMapDataByKey(data: Record<string, any>): Array<any>{
return Object.entries(data)
.sort((a, b) => Number(a[0]) - Number(b[0]))
.map(item => item[1])
}
/**
* Definition for a binary tree node.
* class TreeNode {
* val: number
* left: TreeNode | null
* right: TreeNode | null
* constructor(val?: number, left?: TreeNode | null, right?: TreeNode | null) {
* this.val = (val===undefined ? 0 : val)
* this.left = (left===undefined ? null : left)
* this.right = (right===undefined ? null : right)
* }
* }
*/
function verticalTraversal(root: TreeNode | null): number[][] { const colMap = {}; const diff = (node: TreeNode | null, row: number, col: number) => { if (!node) { return; } if (!colMap[col]) { colMap[col] = []; } colMap[col].push({ val: node.val, row: row, }); if(node.left) { diff(node.left, row + 1, col - 1); } if (node.right) { diff(node.right, row + 1, col + 1); } }; diff(root, 0, 0); return colSort(colMap); };
// 列排序,按照key的大小值排序即可 function colSort (colMap) { return Object.keys(colMap) .sort((a, b) => Number(a) - Number(b)) .map(item => { return colMap[item] .sort((a, b) => { // 如果行不一样,优先用行排序,否则用当前val值排序 if (a.row !== b.row) { return a.row - b.row; } return a.val - b.val; }) .map(node => node.val); }); }
---
### 分析
时间复杂度:?存疑 空间复杂度:O(n)
/**
* Definition for a binary tree node.
* class TreeNode {
* val: number
* left: TreeNode | null
* right: TreeNode | null
* constructor(val?: number, left?: TreeNode | null, right?: TreeNode | null) {
* this.val = (val===undefined ? 0 : val)
* this.left = (left===undefined ? null : left)
* this.right = (right===undefined ? null : right)
* }
* }
*/
interface QueueItem {
x: number;
y: number;
node: TreeNode;
}
function verticalTraversal(root: TreeNode | null): number[][] {
const doubleArr: number[][] = [];
const hashMap: Map<number, number[]> = new Map();
const queue: QueueItem[] = [];
if (root) {
queue.unshift({
x: 0,
y: 0,
node: root
});
}
while(queue.length) {
const levelLen = queue.length;
// 缓存每一层的节点值, x轴都相等
const tempHash: Map<number, number[]> = new Map();
for (let i = 0; i < levelLen; i++) {
const curNode = queue.pop()!;
const { x, y, node } = curNode;
const tempKey = y;
// 如果已存在,说明x,y都相等,这时候就要降序排序
if (tempHash.has(tempKey)) {
const tempVal = tempHash.get(tempKey)!;
tempVal.push(node.val)
tempHash.set(tempKey, tempVal.sort((a, b) => a- b));
} else {
tempHash.set(tempKey, [node.val]);
}
if(node?.left) {
queue.unshift({x: x + 1, y: y - 1, node: node.left });
}
if (node?.right) {
queue.unshift({x: x + 1, y: y + 1, node: node.right })
}
}
// 将临时储存的当前层的节点值,赋值到垂直哈希表中
const tempKeys = Array.from(tempHash.keys());
for (const key of tempKeys) {
const tempVal = tempHash.get(key)!;
if (hashMap.has(key)) {
let hashVal = hashMap.get(key);
hashMap.set(key, (hashVal ?? []).concat(tempVal));
} else {
hashMap.set(key, tempVal);
}
}
tempHash.clear();
}
// 垂直哈希表,进行排序输出即可
const hashKeys = Array.from(hashMap.keys()).sort((a, b) => a - b);
for(const key of hashKeys) {
doubleArr.push(hashMap.get(key)!);
}
return doubleArr;
};
给你二叉树的根结点 root ,请你设计算法计算二叉树的 垂序遍历 序列。
对位于 (row, col) 的每个结点而言,其左右子结点分别位于 (row + 1, col - 1) 和 (row + 1, col + 1) 。树的根结点位于 (0, 0) 。
二叉树的 垂序遍历 从最左边的列开始直到最右边的列结束,按列索引每一列上的所有结点,形成一个按出现位置从上到下排序的有序列表。如果同行同列上有多个结点,则按结点的值从小到大进行排序。
返回二叉树的 垂序遍历 序列。
示例 1:
输入:root = [3,9,20,null,null,15,7] 输出:[[9],[3,15],[20],[7]] 解释: 列 -1 :只有结点 9 在此列中。 列 0 :只有结点 3 和 15 在此列中,按从上到下顺序。 列 1 :只有结点 20 在此列中。 列 2 :只有结点 7 在此列中。 示例 2:
输入:root = [1,2,3,4,5,6,7] 输出:[[4],[2],[1,5,6],[3],[7]] 解释: 列 -2 :只有结点 4 在此列中。 列 -1 :只有结点 2 在此列中。 列 0 :结点 1 、5 和 6 都在此列中。 1 在上面,所以它出现在前面。 5 和 6 位置都是 (2, 0) ,所以按值从小到大排序,5 在 6 的前面。 列 1 :只有结点 3 在此列中。 列 2 :只有结点 7 在此列中。 示例 3:
输入:root = [1,2,3,4,6,5,7] 输出:[[4],[2],[1,5,6],[3],[7]] 解释: 这个示例实际上与示例 2 完全相同,只是结点 5 和 6 在树中的位置发生了交换。 因为 5 和 6 的位置仍然相同,所以答案保持不变,仍然按值从小到大排序。
提示:
树中结点数目总数在范围 [1, 1000] 内 0 <= Node.val <= 1000
来源:力扣(LeetCode) 链接:https://leetcode.cn/problems/vertical-order-traversal-of-a-binary-tree 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。