二叉树 哈希表 广度优先搜索 排序 树 深度优先搜索
题目描述 给你二叉树的根结点 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 解法 方法一:DFS + 排序 我们设计一个函数 \(dfs(root, i, j)\) ,其中 \(i\) 和 \(j\) 表示当前节点的行和列。我们可以通过深度优先搜索的方式,将节点的行和列信息记录下来,存储在一个数组或列表 \(nodes\) 中,然后对 \(nodes\) 按照列、行、值的顺序进行排序。
接着,我们遍历 \(nodes\) ,将相同列的节点值放到同一个列表中,最后返回这些列表。
时间复杂度 \(O(n \times \log n)\) ,空间复杂度 \(O(n)\) 。其中 \(n\) 是二叉树的节点数。
Python3 Java C++ Go TypeScript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26 # Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution :
def verticalTraversal ( self , root : Optional [ TreeNode ]) -> List [ List [ int ]]:
def dfs ( root : Optional [ TreeNode ], i : int , j : int ):
if root is None :
return
nodes . append (( j , i , root . val ))
dfs ( root . left , i + 1 , j - 1 )
dfs ( root . right , i + 1 , j + 1 )
nodes = []
dfs ( root , 0 , 0 )
nodes . sort ()
ans = []
prev = - 2000
for j , _ , val in nodes :
if prev != j :
ans . append ([])
prev = j
ans [ - 1 ] . append ( val )
return ans
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52 /**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
private List < int []> nodes = new ArrayList <> ();
public List < List < Integer >> verticalTraversal ( TreeNode root ) {
dfs ( root , 0 , 0 );
Collections . sort ( nodes , ( a , b ) -> {
if ( a [ 0 ] != b [ 0 ] ) {
return Integer . compare ( a [ 0 ] , b [ 0 ] );
}
if ( a [ 1 ] != b [ 1 ] ) {
return Integer . compare ( a [ 1 ] , b [ 1 ] );
}
return Integer . compare ( a [ 2 ] , b [ 2 ] );
});
List < List < Integer >> ans = new ArrayList <> ();
int prev = - 2000 ;
for ( int [] node : nodes ) {
int j = node [ 0 ] , val = node [ 2 ] ;
if ( prev != j ) {
ans . add ( new ArrayList <> ());
prev = j ;
}
ans . get ( ans . size () - 1 ). add ( val );
}
return ans ;
}
private void dfs ( TreeNode root , int i , int j ) {
if ( root == null ) {
return ;
}
nodes . add ( new int [] { j , i , root . val });
dfs ( root . left , i + 1 , j - 1 );
dfs ( root . right , i + 1 , j + 1 );
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37 /**
* 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 * , int , int ) > dfs = [ & ]( TreeNode * root , int i , int j ) {
if ( ! root ) {
return ;
}
nodes . emplace_back ( j , i , root -> val );
dfs ( root -> left , i + 1 , j - 1 );
dfs ( root -> right , i + 1 , j + 1 );
};
dfs ( root , 0 , 0 );
sort ( nodes . begin (), nodes . end ());
vector < vector < int >> ans ;
int prev = -2000 ;
for ( auto [ j , _ , val ] : nodes ) {
if ( j != prev ) {
prev = j ;
ans . emplace_back ();
}
ans . back (). push_back ( val );
}
return ans ;
}
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35 /**
* Definition for a binary tree node.
* type TreeNode struct {
* Val int
* Left *TreeNode
* Right *TreeNode
* }
*/
func verticalTraversal ( root * TreeNode ) ( ans [][] int ) {
nodes := [][ 3 ] int {}
var dfs func ( * TreeNode , int , int )
dfs = func ( root * TreeNode , i , j int ) {
if root == nil {
return
}
nodes = append ( nodes , [ 3 ] int { j , i , root . Val })
dfs ( root . Left , i + 1 , j - 1 )
dfs ( root . Right , i + 1 , j + 1 )
}
dfs ( root , 0 , 0 )
sort . Slice ( nodes , func ( i , j int ) bool {
a , b := nodes [ i ], nodes [ j ]
return a [ 0 ] < b [ 0 ] || a [ 0 ] == b [ 0 ] && ( a [ 1 ] < b [ 1 ] || a [ 1 ] == b [ 1 ] && a [ 2 ] < b [ 2 ])
})
prev := - 2000
for _ , node := range nodes {
j , val := node [ 0 ], node [ 2 ]
if j != prev {
ans = append ( ans , nil )
prev = j
}
ans [ len ( ans ) - 1 ] = append ( ans [ len ( ans ) - 1 ], val )
}
return
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37 /**
* 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 nodes : [ number , number , number ][] = [];
const dfs = ( root : TreeNode | null , i : number , j : number ) => {
if ( ! root ) {
return ;
}
nodes . push ([ j , i , root . val ]);
dfs ( root . left , i + 1 , j - 1 );
dfs ( root . right , i + 1 , j + 1 );
};
dfs ( root , 0 , 0 );
nodes . sort (( a , b ) => a [ 0 ] - b [ 0 ] || a [ 1 ] - b [ 1 ] || a [ 2 ] - b [ 2 ]);
const ans : number [][] = [];
let prev = - 2000 ;
for ( const [ j , _ , val ] of nodes ) {
if ( j !== prev ) {
prev = j ;
ans . push ([]);
}
ans . at ( - 1 ) ! . push ( val );
}
return ans ;
}
方法二:BFS + 排序 对于任意节点,若其坐标 \((row, col)\) :
左子节点坐标 \((row + 1, col - 1)\) 右子节点坐标 \((row + 1, col + 1)\) 因此在遍历二叉树时,需要同时记录每个节点所在的列信息。
于是我们能使用广度优先搜索遍历整棵二叉树。
题目要求最终结果按照列从左到右输出,因此得维护:
leftmostCol:当前记录的最左列 rightmostCol:当前记录的最右列 同时使用双端队列 columnsValues 存储各列对应的节点值。
当访问到新的列时:
若列号小于 leftmostCol,则在双端队列左侧插入新的列容器; 若列号大于 rightmostCol,则在双端队列右侧插入新的列容器。 对于任意列号 col,其在 columnsValues 中对应的索引为:
\[ col - leftmostCol \]
因此可以在 \(O(1)\) 时间内定位对应列并插入节点值。
完成 BFS 后,每一列中存放了属于该列的所有节点值。
由于 BFS 已经保证了节点按照行从上到下被访问,因此只需要对每一列内部的节点值进行升序排序,即可满足题目的要求。
最后依次输出所有列即可得到答案。
复杂度分析 设二叉树共有 \(n\) 个节点。
Python3 C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45 # Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution :
def verticalTraversal ( self , root : Optional [ TreeNode ]) -> list [ list [ int ]]:
# Format: (tree node, row, column).
queue : deque [ tuple [ TreeNode , int , int ]] = deque ([( root , 0 , 0 )])
# Deque append left speeds up indexing.
# Each tuple format: (row, value).
columns_values : deque [ list [ tuple [ int , int ]]] = deque ([[]])
leftmost_col , rightmost_col = 0 , 0
while queue :
node , row , column = queue . popleft ()
if column < leftmost_col :
leftmost_col = column
columns_values . appendleft ([])
if column > rightmost_col :
rightmost_col = column
columns_values . append ([])
columns_values [ column - leftmost_col ] . append (( row , node . val ))
if node . left :
queue . append (( node . left , row + 1 , column - 1 ))
if node . right :
queue . append (( node . right , row + 1 , column + 1 ))
vertical_traversal : list [ list [ int ]] = []
for column_values in columns_values :
vertical_traversal . append ([])
column_values . sort ()
for _ , value in column_values :
vertical_traversal [ - 1 ] . append ( value )
return vertical_traversal
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58 /**
* 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 ) {
// Each tuple format: {tree node, row, column}.
deque < tuple < TreeNode * , int , int >> queue = {{ root , 0 , 0 }};
// Each tuple format: {row, value}.
deque < vector < tuple < int , int >>> columnsValues = {{}};
int leftmostCol = 0 , rightmostCol = 0 ;
while ( ! queue . empty ()) {
auto [ node , row , column ] = queue . front ();
queue . pop_front ();
if ( column < leftmostCol ) {
leftmostCol = column ;
columnsValues . push_front ({});
}
if ( column > rightmostCol ) {
rightmostCol = column ;
columnsValues . push_back ({});
}
columnsValues [ column - leftmostCol ]. push_back ({ row , node -> val });
if ( node -> left != nullptr )
queue . push_back ({ node -> left , row + 1 , column - 1 });
if ( node -> right != nullptr )
queue . push_back ({ node -> right , row + 1 , column + 1 });
}
vector < vector < int >> verticalTraversal = {};
for ( auto columnValues : columnsValues ) { // Need to sort so no const.
verticalTraversal . push_back ({});
sort ( columnValues . begin (), columnValues . end ());
for ( const auto & [ row , value ] : columnValues )
verticalTraversal . back (). push_back ( value );
}
return verticalTraversal ;
}
};