要求分析:
1、第一次判斷時,如果B爲空,則返回空
2、先判斷B根節點的值,如果B根節點的與A的根節點值相同,則判斷A的左子樹和B的左子樹及A的右子樹和B的右子樹是爲子結構關係。(遞歸)
3、直到判斷到B的節點值與A的節點值相等,而B沒有子樹,則此時爲其子結構
4、如果判斷過程中,B樹的前面部分都爲A樹從節點root1Now開始的一部分,但是最後出現了值不相等,或者B還有子樹而A沒有子樹的情況,則A應該返回至root1Now的左右節點,B應該返回值最初的B。
代碼
/**
public class TreeNode {
int val = 0;
TreeNode left = null;
TreeNode right = null;
public TreeNode(int val) {
this.val = val;
}
}
*/
public class Solution {
TreeNode root1Now=new TreeNode(0);
TreeNode root2Root=new TreeNode(0);
boolean newStart=true;
boolean begin=true;
public boolean HasSubtree(TreeNode root1,TreeNode root2) {
if(begin==true)
{
if(root2==null)
{
return false;
}
else
{
begin=false;
return HasSubtree(root1,root2);
}
}
else
{
if(root2==null)
return true;
else
{
if(root1==null)
return false;
if(root1.val==root2.val)
{
if(newStart ==true)
{
root1Now=root1;
root2Root=root2;
}
newStart=false;
if(HasSubtree(root1.right,root2.right)&&HasSubtree(root1.left,root2.left))/*子樹之間要都是對應的子節點*/
return true;
else
{
newStart=true;
root1=root1Now;
root2=root2Root;
return (HasSubtree(root1.right,root2)||HasSubtree(root1.left,root2));
}
}
else
{
if(newStart==false)/*判斷是否開始了一次左右子樹是否子結構的判斷,如果開始了是否爲左右
子結構的判斷,但是又出現了不相等的情況,則應該直接返回false,然後從之前記錄的位置重新
開始*/
{
return false;
}else return (HasSubtree(root1.right,root2)||HasSubtree(root1.left,root2));
}
}
}
}
}
注意事項(這裏記錄了我寫代碼時出現的bug,看懂以上代碼的可以忽略)
關於遞歸的問題
關於遞歸有不同的調用情況
1、
return (HasSubtree(root1.right,root2)||HasSubtree(root1.left,root2));
這種是這個節點和root2的根節點值不相同,所以應該在root1的左右子樹中繼續找。
2、
if(HasSubtree(root1.right,root2.right)&&HasSubtree(root1.left,root2.left))/*子樹之間要都是對應的子節點*/
return true;
這種情況是必須兩者都是子結構,才能返回true。
但是在再次調用
HasSubtree(root1.right,root2.right)
這個函數的時候,複用了一段關於節點值不相等的時候應該的操作,那這個就應該分兩種情況。
1、如果是在newStart的過程中,就是根節點相等,要判斷子樹的時候。出現了值不相等,則應該直接返回false,這樣HasSubtree(root1.right,root2.right)的查找就會結束,就會退到之前開始的地方。
2、如果不是在newStart的過程中,就是一直在往下找一個相等的節點的時候,則就是直接往下尋找。
我的錯誤
我在第一種情況的時候,沒有返回。而是直接回到了開始的地方,開始新的查找。
但是這時候,他還是屬於
HasSubtree(root1.right,root2.right)&&HasSubtree(root1.left,root2.left)
這個過程中,也就是說,如果是這樣,newStart的值會產生混亂。
root1=root1Now;
root2=root2Root;
的過程沒有辦法得到保證正確。
一次低級錯誤
begin是表示這是第一次執行該函數的標誌,用於實現B一開始就是null時,直接返回false。
正確的代碼如下:
if(begin==true)
{
if(root2==null)
{
return false;
}
else
{
begin=false;
return HasSubtree(root1,root2);
}
}
我寫了一次錯誤代碼爲:
if(begin==true)
{
if(root2==null)
{
return false;
}
}
......
return false /*這裏*/
後面的沒變,但是提示說,缺一個返回,我就在最後隨便寫了個返回 return false ???
我也不知道我在想什麼哦。實際這種問題就是提醒,在裏面這個if裏面,少了一種情況沒有說明。
這裏的情況是沒有變化begin。這樣子直接就是返回false了。這個是基礎錯誤。
參考鏈接
https://www.nowcoder.com/profile/562667/codeBookDetail?submissionId=1523155