摺紙問題
把一段紙條豎着放在桌子上,然後從紙條下方向上方對摺1次,壓出摺痕後展開,此時摺痕是凹下去的。若從紙條下方向上方對摺2次,壓出摺痕後展開,此時有三條摺痕,從上到下依次是下摺痕、下摺痕和上摺痕。給定一個輸入參數N,代表紙條都從下邊向上方連續對摺N次,請從上到下打印所有摺痕的方向。
是一顆滿二叉樹結構,
實現先左再中,最後右的中序遍歷,就是所有摺痕的打印順序(從下到上)。用遞歸實現。
案例
一顆二叉樹原本是搜索二叉樹,但其中有兩個節點調換了位置,使得這棵二叉樹不再是搜索二叉樹,請找到這兩個錯誤節點。
答:
1.對二叉樹中序遍歷,依此出現的節點值會一直升序,如果兩個節點值錯了,會出現降序。
2.若中序遍歷時節點值出現了兩次降序,第一個錯誤的節點爲第一次降序時較大的節點,第二個錯誤的節點爲第二次降序時較小的節點。
3.若中序遍歷時節點值出現了一次降序,第一個錯誤的節點爲這次降序時較大的節點,第二個錯誤的節點爲這次降序時較小的節點。
案例
從二叉樹的節點A出發,可以向上或向下走,但沿途的節點只能經過一次,當到達節點B時,路徑上的節點數叫作A到B的距離。比如大家看到的圖中,節點4和節點2的距離爲2,節點5和節點6的距離爲5。給定一顆二叉樹的頭節點head,求整顆樹上節點間的最大距離。
分析:
一個以h爲頭的樹上,最大距離只可能來自以下三種情況:
情況一:h的左子樹上的最大距離。
情況二:h的右子樹上的最大距離。
情況三:h左子樹上離h左孩子最遠的距離,加上h自身這個節點,再加上h右子樹上離h右孩子的最遠距離,也就是兩個節點分別來自h兩側子樹的情況。
三個值中最大的那個就是以h爲頭的整顆樹上最遠的距離。
步驟:
1、整個過程爲後序遍歷,在二叉樹的每顆子樹上執行步驟2.
2、假設子樹頭爲h,處理h左子樹,得到兩個信息,左子樹上的最大距離記爲LMax1,左子樹上距離h左孩子的最遠距離記爲LMax2。處理h右子樹得到右子樹上的最大距離記爲RMax1,距離h右孩子的最遠距離爲RMax2。那麼跨h節點情況下的最大距離爲LMax2+1+RMax2,這個值與LMax1和RMax1比較,最大值爲 以h爲頭的整棵樹上的最大距離。
3、LMax2+1就是h左子樹上離h最遠的點到h的距離,RMax2+1就是h右子樹上離h最遠的點到h的距離,選兩者中最大的一個作爲h樹上距離h最遠的距離返回。
4、用返回長度爲2的數組的方式,返回兩個值
PS:理解是遞歸思想,但覺得不太對。這個不太懂,還需要細看。
解:
這題寫了很久,但仔細想想,感覺沒那麼難,就是求子樹深度的問題
#include<iostream>
#include<string>
#include<stack>
#include<queue>
using namespace std;
class BinaryTreeNode
{
public:
char data;
BinaryTreeNode *Left;
BinaryTreeNode *Right;
};
//創建二叉樹,順序依次爲中間節點->左子樹->右子樹
void createBiTree(BinaryTreeNode* &T) //這裏加上&意思是傳遞的參數爲指針的引用,括號裏面等價於 BiTreeNode* &T
{ //這樣的意義在於在函數執行過後,傳遞進來的指針會發生改變(引用的作用),不可以去掉&
char c;
cin >> c;
if('#' == c) //當遇到#時,令樹的根節點爲NULL,從而結束該分支的遞歸
T = NULL;
else
{
T = new BinaryTreeNode;
T->data=c;
createBiTree(T->Left);
createBiTree(T->Right);
}
}
int treeDepth(BinaryTreeNode* root){
if(root==NULL){
return 0;
}
if(root->Left==NULL){
return treeDepth(root->Right)+1;
}
if(root->Right==NULL){
return treeDepth(root->Left)+1;
}
return treeDepth(root->Right)>treeDepth(root->Left)?treeDepth(root->Right)+1:treeDepth(root->Left)+1;
}
int max1(int a,int b,int c){
if(a>=b){
if(a>=c){
return a;
}
return c;
}
else if(b>=c)
return b;
else return c;
}
int maxjuli(BinaryTreeNode* root){
if(root==NULL)
return 0;
int Lmax1=maxjuli(root->Left);
int Lmax2=treeDepth(root->Left);
int Rmax1=maxjuli(root->Right);
int Rmax2=treeDepth(root->Right);
return max1(Lmax1,Rmax1,Lmax2+Rmax2);
}
int main(){
BinaryTreeNode* T; //聲明一個指向二叉樹根節點的指針
createBiTree(T); //abcd##e#f#g#h###i##
cout<<"二叉樹創建完成!"<<endl;
cout<<"二叉樹最長距離:"<<endl;
int a=maxjuli(T);
cout<<a<<endl;
return 0;
}
案例
給定一顆二叉樹的頭節點head,已知其中所有節點的值都不一樣,找到含有節點最多的搜索二叉子樹,並返回這顆子樹的頭節點。例如,大家現在看到的圖1這顆樹,最大的搜索子樹就是圖2這棵樹。
以節點node爲頭的樹中,最大的搜索二叉子樹只可能來自以下兩種情況:
1、來自node左子樹上的最大搜索二叉子樹是以node左孩子爲頭的,並且來自node右子樹上的最大搜索二叉樹是以node右孩子爲頭的,node左子樹上的最大搜索二叉子樹的最大值小於node的節點值,node右子樹上的最大搜索二叉子樹的最小值大於node的節點值,那麼以節點node爲頭的整顆樹都是搜索二叉樹。
2、若不滿足第一種情況,說明以node爲頭的樹整體不能連成搜索二叉樹。這種情況下,以node爲頭的樹上的最大搜索二叉子樹是來自node左子樹上的最大搜索二叉子樹和來自node右子樹上的最大搜索二叉子樹之間,節點數較多的那個。
求解具體過程爲:
1.整體過程是二叉樹的後序遍歷。
2.遍歷到當前節點記爲cur,先遍歷cur的左子樹並收集4個信息,分別是左子樹上最大搜索二叉樹的頭節點,節點數,最小值和最大值。再遍歷cur的右子樹並收集4個信息,分別是右子樹上最大搜索二叉樹的頭節點,節點數,最小值和最大值
3.根據步驟2所收集的信息,判斷是否滿足第一種情況,也就是是否以cur爲頭的子樹,整體都是搜索二叉樹。如果滿足第一種情況,就返回cur節點,如果滿足第二種情況,就返回左子樹和右子樹各自的最大搜索二叉樹中,節點數較多的那個樹的頭節點。
4.對於如何返回4個信息,可使用全局變量更新的方式實現,或返回長度爲4的數組。
難點:遞歸過程、收集信息並返回上層。