树
深度优先搜索
广度优先搜索
二叉树
题目描述
在二叉树中,根节点位于深度 0
处,每个深度为 k
的节点的子节点位于深度 k+1
处。
如果二叉树的两个节点深度相同,但 父节点不同 ,则它们是一对堂兄弟节点 。
我们给出了具有唯一值的二叉树的根节点 root
,以及树中两个不同节点的值 x
和 y
。
只有与值 x
和 y
对应的节点是堂兄弟节点时,才返回 true
。否则,返回 false
。
示例 1:
输入: root = [1,2,3,4], x = 4, y = 3
输出: false
示例 2:
输入: root = [1,2,3,null,4,null,5], x = 5, y = 4
输出: true
示例 3:
输入: root = [1,2,3,null,4], x = 2, y = 3
输出: false
提示:
二叉树的节点数介于 2
到 100
之间。
每个节点的值都是唯一的、范围为 1
到 100
的整数。
解法
方法一:BFS
我们定义一个队列 $q$,队列中存储的是节点和其父节点。初始时,将根节点和空节点放入队列中。
每次从队列中取出一个节点,如果该节点的值为 $x$ 或 $y$,则记录该节点的父节点和深度。如果该节点的左右子节点不为空,则将左右子节点和该节点放入队列中。
当队列中所有节点都处理完毕后,如果 $x$ 和 $y$ 的深度相同且父节点不同,则返回 $true$,否则返回 $false$。
时间复杂度 $O(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 # 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 isCousins ( self , root : Optional [ TreeNode ], x : int , y : int ) -> bool :
q = deque ([( root , None )])
depth = 0
p1 = p2 = None
d1 = d2 = None
while q :
for _ in range ( len ( q )):
node , parent = q . popleft ()
if node . val == x :
p1 , d1 = parent , depth
elif node . val == y :
p2 , d2 = parent , depth
if node . left :
q . append (( node . left , node ))
if node . right :
q . append (( node . right , node ))
depth += 1
return p1 != p2 and d1 == d2
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 /**
* 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 {
public boolean isCousins ( TreeNode root , int x , int y ) {
Deque < TreeNode []> q = new ArrayDeque <> ();
q . offer ( new TreeNode [] { root , null });
int d1 = 0 , d2 = 0 ;
TreeNode p1 = null , p2 = null ;
for ( int depth = 0 ; ! q . isEmpty (); ++ depth ) {
for ( int n = q . size (); n > 0 ; -- n ) {
TreeNode [] t = q . poll ();
TreeNode node = t [ 0 ] , parent = t [ 1 ] ;
if ( node . val == x ) {
d1 = depth ;
p1 = parent ;
} else if ( node . val == y ) {
d2 = depth ;
p2 = parent ;
}
if ( node . left != null ) {
q . offer ( new TreeNode [] { node . left , node });
}
if ( node . right != null ) {
q . offer ( new TreeNode [] { node . right , node });
}
}
}
return p1 != p2 && d1 == d2 ;
}
}
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 /**
* 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 :
bool isCousins ( TreeNode * root , int x , int y ) {
queue < pair < TreeNode * , TreeNode *>> q ;
q . push ({ root , nullptr });
int d1 = 0 , d2 = 0 ;
TreeNode * p1 = nullptr , * p2 = nullptr ;
for ( int depth = 0 ; q . size (); ++ depth ) {
for ( int n = q . size (); n ; -- n ) {
auto [ node , parent ] = q . front ();
q . pop ();
if ( node -> val == x ) {
d1 = depth ;
p1 = parent ;
} else if ( node -> val == y ) {
d2 = depth ;
p2 = parent ;
}
if ( node -> left ) {
q . push ({ node -> left , node });
}
if ( node -> right ) {
q . push ({ node -> right , node });
}
}
}
return d1 == d2 && p1 != p2 ;
}
};
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 /**
* Definition for a binary tree node.
* type TreeNode struct {
* Val int
* Left *TreeNode
* Right *TreeNode
* }
*/
func isCousins ( root * TreeNode , x int , y int ) bool {
type pair struct { node , parent * TreeNode }
var d1 , d2 int
var p1 , p2 * TreeNode
q := [] pair {{ root , nil }}
for depth := 0 ; len ( q ) > 0 ; depth ++ {
for n := len ( q ); n > 0 ; n -- {
node , parent := q [ 0 ]. node , q [ 0 ]. parent
q = q [ 1 :]
if node . Val == x {
d1 , p1 = depth , parent
} else if node . Val == y {
d2 , p2 = depth , parent
}
if node . Left != nil {
q = append ( q , pair { node . Left , node })
}
if node . Right != nil {
q = append ( q , pair { node . Right , node })
}
}
}
return d1 == d2 && p1 != p2
}
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 isCousins ( root : TreeNode | null , x : number , y : number ) : boolean {
let [ d1 , d2 ] = [ 0 , 0 ];
let [ p1 , p2 ] = [ null , null ];
const q : [ TreeNode , TreeNode ][] = [[ root , null ]];
for ( let depth = 0 ; q . length > 0 ; ++ depth ) {
const t : [ TreeNode , TreeNode ][] = [];
for ( const [ node , parent ] of q ) {
if ( node . val === x ) {
[ d1 , p1 ] = [ depth , parent ];
} else if ( node . val === y ) {
[ d2 , p2 ] = [ depth , parent ];
}
if ( node . left ) {
t . push ([ node . left , node ]);
}
if ( node . right ) {
t . push ([ node . right , node ]);
}
}
q . splice ( 0 , q . length , ... t );
}
return d1 === d2 && p1 !== p2 ;
}
方法二:DFS
我们设计一个函数 $dfs(root, parent, depth)$,表示从根节点 $root$ 出发,其父节点为 $parent$,深度为 $depth$,进行深度优先搜索。
在函数中,我们首先判断当前节点是否为空,如果为空,则直接返回。如果当前节点的值为 $x$ 或 $y$,则记录该节点的父节点和深度。然后对当前节点的左右子节点分别调用函数 $dfs$,其中父节点为当前节点,深度为当前深度加 $1$。即 $dfs(root.left, root, depth + 1)$ 和 $dfs(root.right, root, depth + 1)$。
当整棵二叉树遍历完毕后,如果 $x$ 和 $y$ 的深度相同且父节点不同,则返回 $true$,否则返回 $false$。
时间复杂度 $O(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 # 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 isCousins ( self , root : Optional [ TreeNode ], x : int , y : int ) -> bool :
def dfs ( root , parent , depth ):
if root is None :
return
if root . val == x :
st [ 0 ] = ( parent , depth )
elif root . val == y :
st [ 1 ] = ( parent , depth )
dfs ( root . left , root , depth + 1 )
dfs ( root . right , root , depth + 1 )
st = [ None , None ]
dfs ( root , None , 0 )
return st [ 0 ][ 0 ] != st [ 1 ][ 0 ] and st [ 0 ][ 1 ] == st [ 1 ][ 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
38
39
40
41
42 /**
* 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 int x , y ;
private int d1 , d2 ;
private TreeNode p1 , p2 ;
public boolean isCousins ( TreeNode root , int x , int y ) {
this . x = x ;
this . y = y ;
dfs ( root , null , 0 );
return p1 != p2 && d1 == d2 ;
}
private void dfs ( TreeNode root , TreeNode parent , int depth ) {
if ( root == null ) {
return ;
}
if ( root . val == x ) {
d1 = depth ;
p1 = parent ;
} else if ( root . val == y ) {
d2 = depth ;
p2 = parent ;
}
dfs ( root . left , root , depth + 1 );
dfs ( root . right , root , depth + 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 /**
* 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 :
bool isCousins ( TreeNode * root , int x , int y ) {
int d1 , d2 ;
TreeNode * p1 ;
TreeNode * p2 ;
function < void ( TreeNode * , TreeNode * , int ) > dfs = [ & ]( TreeNode * root , TreeNode * parent , int depth ) {
if ( ! root ) {
return ;
}
if ( root -> val == x ) {
d1 = depth ;
p1 = parent ;
} else if ( root -> val == y ) {
d2 = depth ;
p2 = parent ;
}
dfs ( root -> left , root , depth + 1 );
dfs ( root -> right , root , depth + 1 );
};
dfs ( root , nullptr , 0 );
return p1 != p2 && d1 == d2 ;
}
};
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 /**
* Definition for a binary tree node.
* type TreeNode struct {
* Val int
* Left *TreeNode
* Right *TreeNode
* }
*/
func isCousins ( root * TreeNode , x int , y int ) bool {
var d1 , d2 int
var p1 , p2 * TreeNode
var dfs func ( root , parent * TreeNode , depth int )
dfs = func ( root , parent * TreeNode , depth int ) {
if root == nil {
return
}
if root . Val == x {
d1 , p1 = depth , parent
} else if root . Val == y {
d2 , p2 = depth , parent
}
dfs ( root . Left , root , depth + 1 )
dfs ( root . Right , root , depth + 1 )
}
dfs ( root , nil , 0 )
return d1 == d2 && p1 != p2
}
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 /**
* 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 isCousins ( root : TreeNode | null , x : number , y : number ) : boolean {
let [ d1 , d2 , p1 , p2 ] = [ 0 , 0 , null , null ];
const dfs = ( root : TreeNode | null , parent : TreeNode | null , depth : number ) => {
if ( ! root ) {
return ;
}
if ( root . val === x ) {
[ d1 , p1 ] = [ depth , parent ];
} else if ( root . val === y ) {
[ d2 , p2 ] = [ depth , parent ];
}
dfs ( root . left , root , depth + 1 );
dfs ( root . right , root , depth + 1 );
};
dfs ( root , null , 0 );
return d1 === d2 && p1 !== p2 ;
}
GitHub