【剑指offer - C++/Java】4、重建二叉树
牛客網題目鏈接:重建二叉樹
文章目錄
- 0 題目描述:
- 1、題目分析
- 2、代碼
- 2.1、java代碼
- 2.2 C++代碼
- 3、總結
0 題目描述:
輸入某二叉樹的前序遍歷和中序遍歷的結果,請重建出該二叉樹。假設輸入的前序遍歷和中序遍歷的結果中都不含重復的數字。例如輸入前序遍歷序列{1,2,4,7,3,5,6,8}和中序遍歷序列{4,7,2,1,5,3,8,6},則重建二叉樹并返回。
1、題目分析
題目給出前序遍歷和中序遍歷,讓重建二叉樹。由前序遍歷特性知前序遍歷的第一個節點,肯定是根節點。那么找到了根節點,接下來找到左子樹與右子樹即可。由中序遍歷的特性知中序遍歷中,根節點位于中間某一個位置,它的左邊是左子樹節點,右邊是右子樹的節點。從而我們就找到了左子樹的所有節點與右子樹的所有節點以及根節點。然后我們讓根節點左指針指向左子樹的根節點,根節點右子樹指針指向右子樹的根節點。那么接下來的問題就是要求左子樹的根節點與右子樹的根節點,然后再讓左子樹的根節點指向它的左子樹與右子樹,右子樹的根節點指向它的左子樹與右子樹…很明顯,這是一個遞歸過程。
下面我們看以下圖示,來理解找根節點,左子樹與右子樹的過程。
假設某一棵樹如下:
它的前序遍歷位:[1,2,4,7,3,5,6,8] 后序遍歷:[4,7,2,1,5,3,8,6]
那么第一次找根節點與左右子樹,如下圖:
此時,可以得出如下我們要求的二叉樹是如下樣式:
以上我們只知道左子樹和右子樹包含哪些節點,并不知道左子樹和右子樹長什么樣。
接下來我們再遞歸的求解左子樹序列與右子樹序列。,找到左子樹的根節點與右子樹的根節點。
遞歸求解左子樹:
此時,可以得出如下二叉樹的形式:
同理,此時對于左子樹的根節點2,再對其遞歸求解它的左子樹與右子樹的二叉樹,其中右子樹位空不用求解直接指向null,左子樹還有節點,那么利用左子樹的節點的前序序列與中序序列,再次遞歸求解即可。
最終得出如下圖所示的左子樹二叉樹:
遞歸求解右子樹:
左子樹遞歸求解完后,就遞歸求解右子樹:
此時可以得到如下二叉樹的形式:
同理,測試再對于右子樹的節點3,再對其進行遞歸求它的左子樹與右子樹,最終得到右子樹的二叉樹為:
所以,最終的二叉樹就是如下圖:
2、代碼
2.1、java代碼
public class Solution {public TreeNode reConstructBinaryTree(int [] pre,int [] in) {if(pre.length-1==0 || in.length-1==0 || pre.length != in.length)return null;return reConstructBinaryTree(pre,0,pre.length-1,in,0,in.length-1);}public TreeNode reConstructBinaryTree(int[] pre,int preStart,int preEnd,int[] in,int inStart,int inEnd){int rootVal=pre[preStart];TreeNode root=new TreeNode(rootVal);//根節點root.left=root.right=null;if(preStart==preEnd || inStart==inEnd)return root;//如果只有一個數了則只有一個節點int inIndex=inStart;//代表中序遍歷中的根節點的位置while(in[inIndex]!=rootVal && inIndex<=inEnd)inIndex++;//找到這個inIndex的位置int lnum=inIndex-inStart;//左子樹節點的個數int rnum=inEnd-inIndex;//右子樹節點的個數if(lnum>0){root.left=reConstructBinaryTree(pre,preStart+1,preStart+lnum,in,inStart,inIndex-1);}if(rnum>0){root.right=reConstructBinaryTree(pre,preStart+lnum+1,preEnd,in,inIndex+1,inEnd);}return root;} }注釋:代碼中inIndex代表中序遍歷中根節點的位置,lnum代表左子樹節點的個數,rnum代表右子樹節點的個數。
2.2 C++代碼
class Solution { public:TreeNode* reConstructBinaryTree(vector<int> pre,vector<int> vin) {if(pre.size()==0 || vin.size()==0 || pre.size()!=vin.size())return nullptr;return reConstructBinaryTree(pre,0,pre.size()-1,vin,0,vin.size()-1);}TreeNode* reConstructBinaryTree(vector<int> pre, int preStart,int preEnd,vector<int> vin, int vinStart,int vinEnd){int rootVal=pre[preStart];TreeNode* root = new TreeNode(rootVal);//根節點root->left=nullptr;root->right=nullptr;if(preStart == preEnd || vinStart==vinEnd)return root;//如果只有一個數了則只有一個節點int vIndex = vinStart;//代表中序遍歷中的根節點的位置while(rootVal != vin[vIndex] && vIndex <= vinEnd)vIndex++;//找到這個vIndex 的位置int lnum = vIndex-vinStart;//左子樹節點的個數int rnum = vinEnd-vIndex;//右子樹節點的個數int leftIndex = preStart+lnum;if(lnum>0){root->left = reConstructBinaryTree(pre,preStart+1,leftIndex,vin,vinStart,vIndex-1);}if(rnum>0){root->right = reConstructBinaryTree(pre,leftIndex+1,preEnd,vin,vIndex+1,vinEnd);}return root;} };注釋:上面vIndex代表中序遍歷中根節點的位置,lnum代表左子樹的節點數目,rnum代表右子樹的節點的數目。
3、總結
以上代碼并不是最簡潔的代碼,但是目的是為了突出這種算法的實現過程。希望每個人都能很容易就理解這種遞歸的過程。
學習探討加:
qq:1126137994
微信:liu1126137994
總結
以上是生活随笔為你收集整理的【剑指offer - C++/Java】4、重建二叉树的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 哪些Amazon erp是可以免费使用的
- 下一篇: win10 平台VS2019最简安装实现