【題目】572. 另一個樹的子樹
給定兩個非空二叉樹 s 和 t,檢驗 s 中是否包含和 t 具有相同結構和節點值的子樹。s 的一個子樹包括 s 的一個節點和這個節點的所有子孫。s 也可以看做它自身的一棵子樹。
示例 1:
給定的樹 s:
3
/ \
4 5
/ \
1 2
給定的樹 t:
4
/ \
1 2
返回 true,因爲 t 與 s 的一個子樹擁有相同的結構和節點值。
示例 2:
給定的樹 s:
3
/ \
4 5
/ \
1 2
/
0
給定的樹 t:
4
/ \
1 2
【解題思路1】比較結點
- 函數 traverse(s,t) 遍歷給定的樹 s 並將每個節點視爲當前正在考慮的子樹的根
- 函數 equals(x,y) 遞歸判斷當前考慮的兩個樹的相等性
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public boolean isSubtree(TreeNode s, TreeNode t) {
return traverse(s, t);
}
private boolean traverse(TreeNode s, TreeNode t) {
return s != null && (equals(s, t) || traverse(s.left, t) || traverse(s.right, t));
}
// 比較兩棵樹是否相等
private boolean equals(TreeNode t1, TreeNode t2) {
if (t1 == null && t2 == null) return true;
else if (t1 == null || t2 == null) return false;
return t1.val == t2.val && equals(t1.left, t2.left) && equals(t1.right, t2.right);
}
}
【解題思路2】先序遍歷-轉化爲字符串
- 求出給定樹 s 和 t 的先序遍歷序列(以字符串形式表示)
- 檢查 t 先序遍歷序列是否是 s 先序遍歷序列的子字符串。
但是,爲了使用這種方法,需要以不同的方式處理給定的樹。不需要爲空葉節點假定 null 值,而是需要分別將空左子節點和空右子節點視爲 lnull 和 rnull 值。
在考慮每個值之前都添加了一個 “#”。如果不這樣做,形式 s:[23, 4, 5] 和 t:[3, 4, 5] 的樹也將給出一個 true 的結果,因爲 t 的先序遍歷字符串 (“23 4 lnull rnull 5 lnull rnull”) 將是 s 的先序遍歷字符串 (“3 4 lnull rull 5 lnull rnull”) 的子字符串。在節點值之前添加一個 “#” 可以解決這個問題。(這段似乎有點問題……?)
class Solution {
public boolean isSubtree(TreeNode s, TreeNode t) {
String tree1 = preOrder(s, true);
String tree2 = preOrder(t, true);
return tree1.indexOf(tree2) >= 0;
}
private String preOrder(TreeNode node, boolean left) {
if (node == null) {
if (left) return "lnull";
else return "rnull";
}
return "#" + node.val + " " + preOrder(node.left, true) + " " + preOrder(node.right, false);
}
}