牛客網常見算法思路 (七)二叉樹

案例一

有用麻煩點個贊哦

遞歸和非遞歸方式實現前中後序遍歷
遞歸:比較簡單不說了
非遞歸:
先序
申請一個棧stack,頭結點壓入stack中,彈出時若右子節點不爲空則將右子節點壓入棧,再若左子節點不爲空則將左子節點壓入棧中,不斷彈出壓入直到結束
中序遍歷
申請一個棧stack,申請一個變量cur=head,
2、先將cur壓入棧中,然後依次將左邊界壓入棧中,重複2,直到cur爲null;
3、此時彈出node,打印,並將cur=node.right節點,繼續重複步驟二
後序遍歷
方法一:用兩個棧實現
1、申請一個棧s1,頭結點壓入s1
2、s1彈出的節點記爲cur,把cur的左孩子壓入s1,然後把cur的右孩子壓入s1
3、整個過程中,每個從s1彈出的節點都放進第二個棧s2中
4、不斷重複步驟2和3,直到s1爲空,過程停止
5、s2中依次彈出節點並打印,打印的順序是後遍歷
方法二:用一個棧實現
1、申請一個棧stack,將頭結點壓入stack,同時設置變量h和c,整個流程中,h代表最近依次彈出並打印的節點,c代表當前stack棧頂節點,初始是h爲頭結點c爲null
2、每次另c等於當前stack的棧頂節點,但從不stack彈出節點。(1)若c的左孩子不爲空,h不等於c的左右孩子(h=c的左右孩子時,說明c的左子樹已經打印完畢了),則將c的左孩子壓入棧中,(2)情況一不成立,若c的右孩子不爲空,h不等於c的右孩子(h=c的右孩子時,說明c的右子樹已經打印完畢了),則將c的右孩子壓入棧中,(3)若12都不成立(證明左右都打印完畢了),則將c彈出,h=c
3、一直重複步驟2直到stack爲空

案例二

二叉樹按層遍歷,每一層打印完則換行
思想
兩個變量last:正在打印的當前行最右節點;nlast:下一行最右節點
遍歷到last節點表示要換行,並last=nlast
創建一個隊列,從head開始,出隊列時將子節點依次放入隊列中
nlast一直等於隊列中最先加入的節點(必定是下一行的最右節點)

案例三

二叉樹序列化和反序列化
之前寫過

案例四

判斷一棵樹是否爲平衡二叉樹
性質葉子節點深度差不超過1
1、判斷左子樹是否爲平衡二叉樹,否則直接返回false
2、左子樹最深到哪一層LH
3、右子樹是否爲平衡二叉樹,否則直接返回false
4、右子樹最深到哪一層RH
5、對比LH和RH

案例五

判斷一棵樹是否爲搜索二叉樹
搜索二叉樹,二叉排序樹(中序遍歷必定是有小到大)
思想:
中序遍歷即可,後一個節點小於前一個節點就不是二叉樹

案例六

判斷一棵樹是否爲完全二叉樹
滿二叉樹
性質:層數爲L,節點數爲N,N=(2的L次方)-1,L=log以2爲底的N+1
完全二叉樹
性質:除最後一層,其他的節點數都是滿的(最後一層也滿叫滿二叉樹),若最後一層不滿,缺少的節點都在右邊,也是完全二叉樹
思路
1、層序遍歷,從左到右
2、若當前節點有右孩子無左孩子,返回false
3、若當前節點並不是左右孩子全有,之後的節點必須爲葉子節點,否則返回false
4、結束後返回true

案例七

新型二叉樹節點(多了一個指向父節點的parent指針,頭結點的parent指向null)
現只給定二叉樹的某個節點node,該節點並不一定是頭結點,可能是樹的任何一個節點,請實現返回node後繼節點的函數
後繼節點,一個及誒單的後繼節點指這個節點中序遍歷的下一個節點(與前驅節點相反)
思路
普通方法
1、通過node節點的parent指針不斷向上找到頭結點
2、通過找到的頭節點,做整棵樹的中序遍歷,再通過該序列找到node的下一個節點O(N)
最優解
如果node節點和後繼節點實際距離爲L,則O(L),空間O(1)
1、若node有右子樹,直接返回右子樹最左邊的節點
2、若無右子樹,那麼先看node是不是父節點的左孩子,是則父節點爲後繼節點
3、若是右孩子,則尋找向上node,向上移動到的節點記爲S,s的父節點爲p,若果發現s是p的左孩子,那麼p就是node的後繼節點,否則向上移動
4、一直向上移動到空節點了還沒找到,證明不存在後繼節點,返回空

案例八

把一段紙豎着放在桌子上,然後從下方向上對着1次,展開,此時摺痕凸起的方向爲紙的背面(下摺痕)
如果對摺兩次,此時有三條摺痕,從上往下依次爲下摺痕、下摺痕、上摺痕
給定參數N,從下向上對着N次,打印摺痕方向
思路:
分析得
第一次 下
第二次 上 下
第三次 上 下 上 下
如此類推 …
先右 再中 最後左的遍歷

案例九

搜索二叉樹,突然出現了兩個節點替換,導致不再是搜索二叉樹了(順序被破壞),請找到這兩個節點
思路:
1、先中序遍歷,出現錯誤節點會出現降序
2、如果出現了兩次降序,第一個錯誤節點爲第一次降序時較大的節點,第二個錯誤爲第二次降序時最小的節點
3、如果出現了一次降序、第一個錯誤節點爲這次比較大的節點、第二個錯誤爲這次比較小的節點

案例十(感覺還是要看代碼,之後會更新)

從二叉樹節點A出發,可以向上或者鄉下走,但沿途的節點只能經過一次,當到達節點b時,路徑上的節點數作爲A到B的距離,給定一棵二叉樹頭結點head,求整個書上節點間的最大距離
思路:
最大距離有以下三種情況
情況一:h的左子樹上的最大距離
情況二:h的右子樹上的最大距離
情況三:h左子樹上h孩子最遠的距離+h自身+h右子樹離h右孩子的最遠距離,三者值中最大的就是最大距離
步驟:
1、整個過程爲後序遍歷,在二叉樹的每棵子樹上執行步驟2
2、假設子樹爲頭h,處理左子樹,得到兩個信息,左子樹上的最大距離爲Lmax1,左子樹上距離h左孩子的最遠距離爲LMax2;處理h右子樹得到的右子樹上最大距離爲RMax1,距離h右孩子的最遠距離記爲RMax2。嘛呢跨h節點情況下最大距離爲Max2+1+RMax2,這個值與LMax1和LMax1相比,比較大的值爲最大距離
3、LMax2+1就是h左子樹上h最遠的點到h的距離,RMax2+1就是h右子樹上離h最遠的點的距離,選兩者中最大的一個作爲h樹上離h最遠的距離返回
4、用返回長度爲2的數組方式,可以做的返回兩個值

案例十一(建議看代碼,之後會更新)

給定一棵二叉樹的頭結點head,一直其中所有節點的值都不一樣,找到含有節點最多的搜索二叉子樹,並返回這棵子樹的頭結點
思路:
遍歷節點,node會是以下兩種情況
1、node是最大搜索二叉樹的節點頭:node左子樹下的最大搜索二叉子樹是以node左孩子爲頭的,且來自node右子樹上的最大搜索二叉子樹是以node右孩子爲頭的,node左子樹上最大值小於node,node右子樹上的最大搜索二叉子樹的最小值大於node
2、不滿足第一種情況證明以節點node爲頭的樹整體不能連成搜索二叉樹,以node爲頭的樹最大搜索二叉子樹來自node左孩子右孩子爲頭的最大搜索二叉子樹中,節點數較多的那個
步驟:
1、整體過程後序遍歷
2、遍歷到的當前節點即爲cur時,先遍歷cur的左子樹並收集4個信息,分別是左子樹上,最大收縮子樹的頭結點、節點數、樹上最小值、最大值;再遍歷cur右節點收集這4個信息,分別是右子樹上最大搜索二叉子樹的頭結點、節點數、最小值、最大值
3、根據2收集的信息,判斷是否滿足情況一,是則返回cur節點,否則返回左右孩子爲頭的最大搜索二叉樹中節點最多的數的頭結點

有用麻煩點個贊哦

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章