生活随笔
收集整理的這篇文章主要介紹了
二叉树入门题
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
題目
序號題目難度本文外鏈方法
| 1. | 單值二叉樹 | 簡單 | 跳轉 | LeetCode | 遞歸 |
| 2. | 二叉樹深度 | 簡單 | 跳轉 | LeetCode | 遞歸 |
| 3. | 翻轉二叉樹 | 簡單 | 跳轉 | LeetCode | 遞歸 |
| 4. | 相同的樹 | 簡單 | 跳轉 | LeetCode | 遞歸 |
| 5. | 是否為子樹 | 簡單 | 跳轉 | LeetCode | 遞歸 |
| 6. | 對稱二叉樹 | 簡單 | 跳轉 | LeetCode | 遞歸 |
| 7. | 平衡二叉樹 | 簡單 | 跳轉 | LeetCode | 遞歸 |
| 8. | 重建二叉樹 | 中等 | 跳轉 | 牛客 | 遞歸 |
單值二叉樹
題目
解法一
本題解法很簡單,把任何一顆樹看作當前樹+子樹。判斷當前樹時,如果左孩子存在,同時左孩子的值和根節點值不同返回false,如果右孩子存在,同時右孩子的值和根節點值不同返回false。最后對子樹進行遞歸,也即return 左子樹&&右子樹,有一顆樹出現false,整個樹不是單值二叉樹
其中注意:空樹屬于單值二叉樹
bool
isUnivalTree(struct TreeNode* root
)
{if(root
==NULL)return true
;if(root
->left
&&root
->val
!=root
->left
->val
)return false
;if(root
->right
&&root
->val
!=root
->right
->val
)return false
;return isUnivalTree(root
->left
)&&isUnivalTree(root
->right
);}
解法二
還是用遞歸,使用標記的方法進行。開始默認它是單值二叉樹,然后進入遞歸,此過程訪問結點,用結點的值和根節點比較,如果不同,修改這個標記,直到遞歸結束,在主函數內判斷,若標記不是原來的值了,則不是單值二叉樹,如果沒有改變,則是單值二叉樹。注意傳入標記時,使用地址
void preorder(struct TreeNode* cur
,int* x
,int head
)
{if(cur
== NULL)return;if(cur
->val
!=head
)*x
=0;preorder(cur
->left
,x
,head
);preorder(cur
->right
,x
,head
);}bool
isUnivalTree(struct TreeNode* root
)
{if(root
==NULL)return false
;int x
=1;int head
=root
->val
;preorder(root
,&x
,head
);if(x
==0)return false
;elsereturn true
;
}
二叉樹最大深度
題目
解法
這是一個遞歸問題,劃分子問題即可。樹的深度=左子樹的深度和右子樹深度大者取其并加1.。這里注意使用三目運算符時,不要重復遞歸,否則時間復雜度過高
int maxDepth(struct TreeNode* root
)
{if(root
==NULL)return 0;int leftdeep
=maxDepth(root
->left
);int rightdeep
=maxDepth(root
->right
);return leftdeep
>rightdeep
?leftdeep
+1:rightdeep
+1;}
翻轉二叉樹
題目
解法
此題比較簡單,只需遞歸,每次遞歸時交換根節點的兩個孩子即可
struct TreeNode* invertTree(struct TreeNode* root
)
{if(root
!= NULL){struct TreeNode* cur
=root
->left
;root
->left
=root
->right
;root
->right
=cur
;invertTree(root
->left
);invertTree(root
->right
);}return root
;
}
相同的樹
題目
解法
此題也屬于遞歸。如果結構相同同時值相同那么就去判斷其子樹(遞歸),注意中間會有一種特殊情況,如果p和q同時為NULL,這時的二叉樹沒有右子樹,屬于單鏈的二叉樹
bool
isSameTree(struct TreeNode* p
, struct TreeNode* q
)
{if((p
&&q
)&&(p
->val
==q
->val
))return isSameTree(p
->left
,q
->left
)&&isSameTree(p
->right
,q
->right
);else if(p
==NULL&&q
==NULL)return true
;elsereturn false
;
}
是否為子樹
題目
本題可以借助相同的樹,如果某一時刻,根節點相同并且其子樹也相同,那么就存在子樹。注意后面遞歸時是“或”,因為如果左樹沒有子樹,還要去右樹找。
bool
isSameTree(struct TreeNode* p
, struct TreeNode* q
)
{if((p
==NULL&&q
==NULL))return true
;if((p
&&q
)&&(p
->val
==q
->val
))return isSameTree(p
->left
,q
->left
)&&isSameTree(p
->right
,q
->right
);elsereturn false
;
}bool
isSubtree(struct TreeNode* s
, struct TreeNode* t
)
{if(s
==NULL)return false
;else if(s
->val
==t
->val
&& isSameTree(s
,t
))return true
;elsereturn isSubtree(s
->left
,t
)||isSubtree(s
->right
,t
);}
對稱二叉樹
題目
解法
如果一棵樹它的左子樹和右子樹是呈現鏡像的,那么就是對稱二叉樹。
下面這棵樹是一棵對稱二叉樹,是因為根節點的左孩子的左孩子和根節點的右孩子的右孩子是相同的,同時根節點的左孩子的右孩子和根節點的右孩子的左孩子是相同的。
bool
check(struct TreeNode* ll
,struct TreeNode* rr
)
{if(ll
==NULL && rr
==NULL)return true
;else(ll
==NULL || rr
=NULL)return false
;return ll
->val
==rr
->val
&& check(ll
->left
,rr
->right
) && check(ll
->right
,rr
->left
);
}bool
isSymmetric(struct TreeNode* root
)
{return check(root
,root
);}
平衡二叉樹
題目
解法一
根據平衡二叉樹的定義,如果某個結點的左子樹之差大于1那么就不是空樹,如果小于,則遞歸,看它左子樹和右子樹的情況
```c
int depth(struct TreeNode* root
)
{if(root
==NULL)return 0;int leftdeep
=depth(root
->left
);int rightdeep
=depth(root
->right
);return leftdeep
>rightdeep
?leftdeep
+1:rightdeep
+1;}bool
isBalanced(struct TreeNode* root
)
{if(root
==NULL)return true
;if(abs(depth(root
->left
)-depth(root
->right
))>1){return false
;}return isBalanced(root
->left
)&& isBalanced(root
->right
);
}
解法二
解法一本質采取的就是前序遍歷,有一個非常大的缺點,就是高度在重復計算,根節點算了高度,用于判斷根節點,然后第二層結點又去計算,從而使時間復雜度變大。
所以可以優化,才后序遍歷,從最底層開始,如果這一層滿足平衡,那么就給上一層返回true,同時返回自身高度
bool
check(struct TtreeNode* root
,int* depth
)
{if(root
==NULL){*depth
=0;return true
;}else{int leftdepth
=0;if(check(root
->left
,&leftdepth
)==false
)return false
;int rightdepth
=0;if(check(root
->right
,&rightdepth
)==false
)return false
;if(abs(leftdepth
-rightdepth
)>1)return false
;*depth
=leftdepth
>rightdepth
?leftdepth
+1:rightdepth
+1;return true
;}
}
bool
isBalanced(struct TreeNode* root
)
{int depth
=0;return check(root
,&depth
);}
重建二叉樹
解法
實則是一個遞歸過程。每遇到一個新節點,就把它當做先序遍歷的根節點進行構造,遇到#就為NULL,當一個結點的左右子樹構造完成時,可以將該節點連接到上方結點,作為上一個結點孩子結點
#include <stdio.h>typedef struct BTNode
{char val
;struct BTNode* lchild
;struct BTNode* rchild
;
}BTNode
;BTNode
* CreatTree(char* str
,int* i
)
{if(str
[*i
]=='#'){(*i
)++;return NULL;}else{BTNode
* root
=(BTNode
*)malloc(sizeof(BTNode
));root
->val
=str
[*i
];(*i
)++;root
->lchild
=CreatTree(str
,i
);root
->rchild
=CreatTree(str
,i
);return root
;}}void Inorder(BTNode
* root
)
{if(root
==NULL)return;Inorder(root
->lchild
);printf("%c ",root
->val
);Inorder(root
->rchild
);}
int main()
{char str
[100];scanf("%s",str
);int i
=0;Inorder(CreatTree(str
,&i
));
}
總結
以上是生活随笔為你收集整理的二叉树入门题的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。