生活随笔
收集整理的這篇文章主要介紹了
二叉树入门题
小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
題目
序號(hào)題目難度本文外鏈方法
| 1. | 單值二叉樹 | 簡(jiǎn)單 | 跳轉(zhuǎn) | LeetCode | 遞歸 |
| 2. | 二叉樹深度 | 簡(jiǎn)單 | 跳轉(zhuǎn) | LeetCode | 遞歸 |
| 3. | 翻轉(zhuǎn)二叉樹 | 簡(jiǎn)單 | 跳轉(zhuǎn) | LeetCode | 遞歸 |
| 4. | 相同的樹 | 簡(jiǎn)單 | 跳轉(zhuǎn) | LeetCode | 遞歸 |
| 5. | 是否為子樹 | 簡(jiǎn)單 | 跳轉(zhuǎn) | LeetCode | 遞歸 |
| 6. | 對(duì)稱二叉樹 | 簡(jiǎn)單 | 跳轉(zhuǎn) | LeetCode | 遞歸 |
| 7. | 平衡二叉樹 | 簡(jiǎn)單 | 跳轉(zhuǎn) | LeetCode | 遞歸 |
| 8. | 重建二叉樹 | 中等 | 跳轉(zhuǎn) | 牛客 | 遞歸 |
單值二叉樹
題目
解法一
本題解法很簡(jiǎn)單,把任何一顆樹看作當(dāng)前樹+子樹。判斷當(dāng)前樹時(shí),如果左孩子存在,同時(shí)左孩子的值和根節(jié)點(diǎn)值不同返回false,如果右孩子存在,同時(shí)右孩子的值和根節(jié)點(diǎn)值不同返回false。最后對(duì)子樹進(jìn)行遞歸,也即return 左子樹&&右子樹,有一顆樹出現(xiàn)false,整個(gè)樹不是單值二叉樹
其中注意:空樹屬于單值二叉樹
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
);}
解法二
還是用遞歸,使用標(biāo)記的方法進(jìn)行。開(kāi)始默認(rèn)它是單值二叉樹,然后進(jìn)入遞歸,此過(guò)程訪問(wèn)結(jié)點(diǎn),用結(jié)點(diǎn)的值和根節(jié)點(diǎn)比較,如果不同,修改這個(gè)標(biāo)記,直到遞歸結(jié)束,在主函數(shù)內(nèi)判斷,若標(biāo)記不是原來(lái)的值了,則不是單值二叉樹,如果沒(méi)有改變,則是單值二叉樹。注意傳入標(biāo)記時(shí),使用地址
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
;
}
二叉樹最大深度
題目
解法
這是一個(gè)遞歸問(wèn)題,劃分子問(wèn)題即可。樹的深度=左子樹的深度和右子樹深度大者取其并加1.。這里注意使用三目運(yùn)算符時(shí),不要重復(fù)遞歸,否則時(shí)間復(fù)雜度過(guò)高
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;}
翻轉(zhuǎn)二叉樹
題目
解法
此題比較簡(jiǎn)單,只需遞歸,每次遞歸時(shí)交換根節(jié)點(diǎn)的兩個(gè)孩子即可
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
;
}
相同的樹
題目
解法
此題也屬于遞歸。如果結(jié)構(gòu)相同同時(shí)值相同那么就去判斷其子樹(遞歸),注意中間會(huì)有一種特殊情況,如果p和q同時(shí)為NULL,這時(shí)的二叉樹沒(méi)有右子樹,屬于單鏈的二叉樹
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
;
}
是否為子樹
題目
本題可以借助相同的樹,如果某一時(shí)刻,根節(jié)點(diǎn)相同并且其子樹也相同,那么就存在子樹。注意后面遞歸時(shí)是“或”,因?yàn)槿绻髽錄](méi)有子樹,還要去右樹找。
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
);}
對(duì)稱二叉樹
題目
解法
如果一棵樹它的左子樹和右子樹是呈現(xiàn)鏡像的,那么就是對(duì)稱二叉樹。
下面這棵樹是一棵對(duì)稱二叉樹,是因?yàn)楦?jié)點(diǎn)的左孩子的左孩子和根節(jié)點(diǎn)的右孩子的右孩子是相同的,同時(shí)根節(jié)點(diǎn)的左孩子的右孩子和根節(jié)點(diǎn)的右孩子的左孩子是相同的。
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
);}
平衡二叉樹
題目
解法一
根據(jù)平衡二叉樹的定義,如果某個(gè)結(jié)點(diǎn)的左子樹之差大于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
);
}
解法二
解法一本質(zhì)采取的就是前序遍歷,有一個(gè)非常大的缺點(diǎn),就是高度在重復(fù)計(jì)算,根節(jié)點(diǎn)算了高度,用于判斷根節(jié)點(diǎn),然后第二層結(jié)點(diǎn)又去計(jì)算,從而使時(shí)間復(fù)雜度變大。
所以可以優(yōu)化,才后序遍歷,從最底層開(kāi)始,如果這一層滿足平衡,那么就給上一層返回true,同時(shí)返回自身高度
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
);}
重建二叉樹
解法
實(shí)則是一個(gè)遞歸過(guò)程。每遇到一個(gè)新節(jié)點(diǎn),就把它當(dāng)做先序遍歷的根節(jié)點(diǎn)進(jìn)行構(gòu)造,遇到#就為NULL,當(dāng)一個(gè)結(jié)點(diǎn)的左右子樹構(gòu)造完成時(shí),可以將該節(jié)點(diǎn)連接到上方結(jié)點(diǎn),作為上一個(gè)結(jié)點(diǎn)孩子結(jié)點(diǎn)
#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
));
}
總結(jié)
以上是生活随笔為你收集整理的二叉树入门题的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。