版權聲明:本文為博主原創文章,未經博主允許不得轉載。
題目描述:
輸入兩棵二叉樹A,B,判斷B是不是A的子結構。(ps:我們約定空樹不是任意一個樹的子結構)。
解題思路:
首先看牛客網給出的測試用例:
一般對於樹的操作不像鏈表一樣,操作更復雜,如果使用循環遍歷的話,對於非完全二叉樹規律難尋,一般通用的方法就是使用遞歸求解,本題也不例外,同樣使用遞歸求解,求解的大體思路是首先判斷B的根節點和A的根節點是否相同(這里的相同是指節點的值相同並且左右子節點相同),如果相同比較他們的左右子節點,這一步驟是相同的,可以用遞歸完成,直到B遍歷到每個尾節點,如果這一過程比較的所有節點是相同的,則證明B是A的子結構。如果B的根節點和A的根節點不同,則A向他的左右子節點滑動,然后繼續跟B的子節點比較,步驟同上。
遞歸的使用可以用我總結的三步來完成。求解過程如下:
1. 遞歸截止條件。
遞歸的截止條件是為了遞歸能夠避免無限循環下去,首先來分析什么情況下遞歸截止返回遍歷結果,(1)根據題目要求,如果B數是個空樹,遞歸截止。(2)如果被遍歷的樹A是空樹,自然而然遞歸截止。(3)如果比較的是B的尾節點,無法進行下去,遞歸也會截止。(4)如果A樹從頭遍歷到尾始終沒有和B的節點相同的節點,遞歸截止。
2. 遞歸的前后銜接。
如果A的根節點值以及左右子節點情況和B的根節點完全相同,那么A和B都繼續滑動到他們的左右子節點進行比較;如果A的根節點值和B的根節點值是相同的,但是左右子節點的情況是不相同的,那么只滑動A到他的左右子節點再與B比較。如果A的根節點的值和B的根節點的值不相同,那么A直接滑動到他的左右自己點再和B的根節點比較,直到遍歷完成。
3. 遞歸節點數據的處理。
根據題目,本題目中用到的遞歸並沒有數據處理,只是比較判斷兩個樹節點是否相同。對於其他遞歸,可以具體情況具體對待。
源碼:
1 /** 2 * 輸入兩棵二叉樹A,B,判斷B是不是A的子結構。 3 * @param root1 A樹 4 * @param root2 B數 5 * @return 6 */ 7 public static boolean HasSubtree(TreeNode root1,TreeNode root2) { 8 9 if (root2==null) { //空樹不是任意一個樹的子結構 10 return false; 11 } 12 if (root1==null) { //如果A為空,那肯定返回false 13 return false; 14 } 15 if(root2.val==root1.val){ //A和B比較的根節點的值相同 16 17 if (root2.left==null&&root2.right==null) { //比較的節點是B的尾節點,遞歸截止 18 return true; 19 } 20 //下面三種比較的是比較的節點完全相同的情況 21 if ((root2.left!=null&&root2.right!=null)&&(root1.left!=null&&root1.right!=null)&&root2.left.val==root1.left.val&&root2.right.val==root1.right.val) { 22 return HasSubtree(root1.left,root2.left)&& HasSubtree(root1.right,root2.right); 23 }else if ((root2.left!=null&&root2.right==null)&&(root1.left!=null&&root1.right==null)&&root2.left.val==root1.left.val) { 24 return HasSubtree(root1.left,root2.left); 25 }else if ((root2.left==null&&root2.right!=null)&&(root1.left==null&&root1.right!=null)&&root2.right.val==root1.right.val) { 26 return HasSubtree(root1.right,root2.right); 27 }else{ //比較的節點不同,A向左右子節點移動一個再比較 28 if (root1.left!=null&&root1.right!=null) { 29 return HasSubtree(root1.left,root2)|| HasSubtree(root1.right,root2); 30 }else if(root1.left==null&&root1.right!=null){ 31 return HasSubtree(root1.right,root2); 32 }else if(root1.left!=null&&root1.right==null){ 33 return HasSubtree(root1.left,root2); 34 }else { 35 return false; 36 } 37 } 38 //比較的根節點的值不相同,直接向左右子節點滑動 39 }else if(root1.left!=null&&root1.right==null){ 40 return HasSubtree(root1.left,root2); 41 }else if(root1.left==null&&root1.right!=null){ 42 return HasSubtree(root1.right,root2); 43 }else{ 44 return false; 45 } 46 }