4.8 You have two very large binary trees: Tl, with millions of nodes, and T2, with hundreds of nodes. Create an algorithm to decide if T2 is a subtree of Tl. A tree T2 is a subtree of Tl if there exists a node n in Tl such that the subtree of n is identical to T2. That is, if you cut off the tree at node n, the two trees would be identical.
這道題給我們兩棵樹,T1和T2,其中T1有百萬個節點,T2有上百個節點,讓我們寫演算法來判斷T2是不是T1的子樹。首先可以用的方法是,我們對兩棵樹分別進行前序和中序遍歷,然後把結果分別存入字串中,如果T2的前序和中序遍歷的字串分別是T1的前序和中序遍歷的字串的子串,那麼我們可以判定T2是T1的子樹,參見程式碼如下:
解法一:
class Solution { public: bool containTree(TreeNode *root1, TreeNode *root2) { string pre1, pre2, in1, in2; preorder(root1, pre1); preorder(root2, pre2); inorder(root1, in1); inorder(root2, in2); if (pre1.find(pre2) == pre1.size() - pre2.size() && in1.find(in2) == in1.size() - in2.size()) return true; else return false; } void preorder(TreeNode *root, string &res) { if (!root) return; res.append(to_string(root->val)); preorder(root->left, res); preorder(root->right, res); } void inorder(TreeNode *root, string &res) { if (!root) return; inorder(root->left, res); res.append(to_string(root->val)); inorder(root->right, res); } };
但是上面這種解法存在例外情況無法正確分辨,比如下面的兩棵樹:
3 3
/ and \
3 3
它們的中序和前序遍歷都相同,所以上述演算法會返回true,但我們知道它們是兩個不同的樹,誰也不包含誰,誰也不是誰的子樹。Cracking the Coding Interview 5th Edition這書上第235頁上說我們可以標記處空節點,但這種方法麻煩,又佔空間,所以這裡我不去寫它。下面來看書上給出的另一種解法,這種解法的思路是,我們首先判斷T2是否為空,為空則直接返回True,因為空樹是任何樹的子樹,然後我們看T1是否為空,T1為空直接返回false,因為空樹不可能有非空子樹,然後我們看兩個根節點的值是否相同,如果相同,則呼叫matchTree方法,來比較整個T2樹,如果完全匹配則返回true,否則繼續往下遞迴,參見程式碼如下:
解法二:
class Solution { public: bool containTree(TreeNode *root1, TreeNode *root2) { if (!root2) return true; if (!root1) return false; if (root1->val == root2->val) { if (matchTree(root1, root2)) return true; } return containTree(root1->left, root2) || containTree(root1->right, root2); } bool matchTree(TreeNode *root1, TreeNode *root2) { if (!root1 && !root2) return true; if (!root1 || !root2) return false; if (root1->val != root2->val) return false; else (matchTree(root1->left, root2->left) && matchTree(root1->right, root2->right)); } };