1. 程式人生 > 其它 >劍指Offer26.樹的子結構

劍指Offer26.樹的子結構

題目

輸入兩棵二叉樹A和B,判斷B是不是A的子結構。(約定空樹不是任意一個樹的子結構)

B是A的子結構, 即 A中有出現和B相同的結構和節點值。

例如:
給定的樹 A:

3
/ \
4  5
/ \
1  2
給定的樹 B:

4
/
1
返回 true,因為 B 與 A 的一個子樹擁有相同的結構和節點值。

示例 1:

輸入:A = [1,2,3], B = [3,1]
輸出:false
示例 2:

輸入:A = [3,4,5,1,2], B = [4,1]
輸出:true
限制:

0 <= 節點個數 <= 10000

來源:力扣(LeetCode)
連結:https://leetcode-cn.com/problems/shu-de-zi-jie-gou-lcof


著作權歸領釦網路所有。商業轉載請聯絡官方授權,非商業轉載請註明出處。

解題思路

遞迴

首先先序遍歷A樹,找到B樹的根節點
找到B樹的根節點以後進一步校驗B是否和A的一個子樹擁有相同的結構和節點值
主函式:
    如果兩棵樹都為空,返回true
    如果其中一顆樹為空,返回false
    如果當前A樹節點為B樹根節點,進入校驗函式
    如果當前A樹節點不是B樹根# 題目

輸入兩棵二叉樹A和B,判斷B是不是A的子結構。(約定空樹不是任意一個樹的子結構)

B是A的子結構, 即 A中有出現和B相同的結構和節點值。

例如:
給定的樹 A:

3
/ \
4  5
/ \
1  2
給定的樹 B:

4
/
1
返回 true,因為 B 與 A 的一個子樹擁有相同的結構和節點值。

示例 1:

輸入:A = [1,2,3], B = [3,1]
輸出:false
示例 2:

輸入:A = [3,4,5,1,2], B = [4,1]
輸出:true
限制:

0 <= 節點個數 <= 10000

來源:力扣(LeetCode)
連結:https://leetcode-cn.com/problems/shu-de-zi-jie-gou-lcof
著作權歸領釦網路所有。商業轉載請聯絡官方授權,非商業轉載請註明出處。

解題思路

遞迴

首先先序遍歷A樹,找到B樹的根節點
找到B樹的根節點以後進一步校驗B是否和A的一個子樹擁有相同的結構和節點值
主函式:
    如果兩棵樹都為空,返回true
    如果其中一顆樹為空,返回false
    如果當前A樹節點為B樹根節點,進入校驗函式
    如果當前A樹節點不是B樹根節點,遞迴進入A樹左子樹查詢
    如果A樹左子樹也沒找到,遞迴進入A樹右子樹查詢
校驗函式:
    如果B樹節點為空,表示B樹已經遍歷完,返回true
    如果B樹不為空,A樹已經為空了,返回false
    如果兩樹節點值不同,返回false
    如果兩樹節點值相同,遞迴繼續效驗左右子樹

時間複雜度 O(MN): 其中 M,N 分別為樹 A 和 樹 B 的節點數量
空間複雜度 O(M) : 當樹 A 和樹 B 都退化為連結串列時,遞迴呼叫深度最大。節點,遞迴進入A樹左子樹查詢
    如果A樹左子樹也沒找到,遞迴進入A樹右子樹查詢
校驗函式:
    如果B樹節點為空,表示B樹已經遍歷完,返回true
    如果B樹不為空,A樹已經為空了,返回false
    如果兩樹節點值不同,返回false
    如果兩樹節點值相同,遞迴繼續效驗左右子樹

時間複雜度 O(MN): 其中 M,N 分別為樹 A 和 樹 B 的節點數量
空間複雜度 O(M) : 當樹 A 和樹 B 都退化為連結串列時,遞迴呼叫深度最大。

/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func isSubStructure(A *TreeNode, B *TreeNode) bool {
	if A == nil && B == nil{
		return true
	}
	// 空二叉樹不屬於任何樹子樹
	if A == nil || B == nil{
		return false
	}
	//var ret bool
	//if A.Val == B.Val{
	//	ret = helper(A,B)
	//}
	//if !ret{
	//	ret = isSubStructure(A.Left,B)
	//}
	//if !ret{
	//	ret = isSubStructure(A.Right,B)
	//}
	//return ret
	// 判斷兩二叉樹根節點是否相等,如果相等則繼續遞迴左右判斷是否包含整個子樹
	// 如果不相等,遞迴左子樹
	// 如果A左子樹也沒有包含B樹的,遞迴右子樹
	return helper(A,B) || isSubStructure(A.Left,B) || isSubStructure(A.Right,B)
}

func helper(a *TreeNode,b *TreeNode) bool {
	// b樹為空,說明遍歷完了,A中包含子樹B
	if b == nil{
		return true
	}
	// a樹為空,說明A樹遍歷完了,但B樹還有,所以A樹不包含子樹B
	if a == nil{
		return false
	}
	// a樹和b樹節點不相等
	if a.Val != b.Val{
		return false
	}
	// 如果相等,繼續遞迴左右子樹判斷剩餘部分是否符合
	return helper(a.Left,b.Left) && helper(a.Right,b.Right)
}