演算法學習記錄四(C++)--->通過前序和中序序列重建二叉樹
描述
- 輸入某二叉樹的前序遍歷和中序遍歷的結果,請重建出該二叉樹。假設輸入的前序遍歷和中序遍歷的結果中都不含重複的數字。例如輸入前序遍歷序列{1,2,4,7,3,5,6,8}和中序遍歷序列{4,7,2,1,5,3,8,6},則重建二叉樹並返回。
思路
- 前序 DLR —> 根左右 第一個元素就是當前根節點
- 中序 LDR —> 左根右 根元素分割了左子樹和右子樹
1.我們首先從前序中找到第一個元素建立,就是根節點,然後拿這個根節點去中序序列中遍歷,找到後左側就是左子樹,右側就是右子樹
2.然後分別通過數量,找到前序中的左右子樹,然後再進行前中左子樹和前中右子樹進行遞迴,直到葉節點不在有子樹
3.先看下第一個例子,每次遞迴都建立出前序左右子樹vector和中序左右子樹vectot
/**
* Definition for binary tree
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
TreeNode* reConstructBinaryTree(vector<int> pre,vector<int> vin) {
int inLenth = vin.size();
// 遞迴結束的時候 vector為空
if(inLenth == 0)
return NULL;
// 每次遞迴都建立新的向量 儲存DLR和LDR的L和R
vector<int> left_pre,right_pre,left_in,right_in;
//建立根節點,根節點肯定是前序遍歷的第一個數
TreeNode* head=new TreeNode(pre[0]);
//對於中序遍歷,根節點左邊的節點位於二叉樹的左邊,根節點右邊的節點位於二叉樹的右邊
// 通過DLR的第一個數字,鎖定LDR中左右子樹的分割線
int gen = 0;
for(int i = 0;i<inLenth;i++){
if(vin[i] == pre[0]){
gen = i;
break;
}
}
// 獲取中前序中的左子樹
for(int i = 0;i<gen;i++){
left_pre.push_back(pre[i+1]);
left_in.push_back(vin[i]);
}
// 這裡一定要從gen+1開始遍歷,避免出現陣列越界
// 獲取中前序中的右子樹
for(int i = gen+1;i<inLenth;i++){
right_pre.push_back(pre[i]);
right_in.push_back(vin[i]);
}
// 遞迴,每次把對應深度的跟節點返回,進行逆向迴歸
//和shell排序的思想類似,取出前序和中序遍歷根節點左邊和右邊的子樹
//遞迴,再對其進行上述所有步驟,即再區分子樹的左、右子子數,直到葉節點
head->left = reConstructBinaryTree(left_pre,left_in);
head->right = reConstructBinaryTree(right_pre,right_in);
return head;
}
};
更加精簡
- 通過初始出來的前序序列和中序序列,只是改變其子樹的起始和終點進行遞迴遍歷
class Solution {
public:
TreeNode* reConstructBinaryTree(vector<int> pre,vector<int> vin) {
return Find(pre, 0, pre.size() - 1, vin, 0, vin.size() - 1);
}
private:
TreeNode* Find(const vector<int> &pre,int p_begin,int p_end,const vector<int> &vin,int v_begin,int v_end){
// 遞迴結束 當開始的下標大於結束的下標,表示已經沒有子樹了
if(p_begin > p_end || v_begin > v_end){
return NULL;
}
// 前序 DLR-> 第一個數就是根節點
TreeNode *root = new TreeNode(pre[p_begin]);
// 遍歷 中序 LDR 分割出左子樹和右子樹
int i = v_begin;
for(;i<=v_end;i++){
if(vin[i] == pre[p_begin]){
break;
}
}
// 獲取左子樹的數量和右子樹的數量
int left_num = i-v_begin;
int right_num = v_end - i;
// 左右子樹分別進行遞迴
root->left = left_num == 0 ? NULL : Find(pre,p_begin+1,p_begin+left_num,vin,v_begin,i);
root->right = right_num == 0 ? NULL : Find(pre,p_begin+left_num+1,p_end,vin,i+1,v_end);
return root;
}
};
相關文章
- 根據前序遍歷序列、中序遍歷序列,重建二叉樹二叉樹
- 二叉樹 前序、中序、後序二叉樹
- 【劍指offer】【4】根據前序和中序結果,重建二叉樹二叉樹
- 二叉樹:構造二叉樹(通過前序和中序遍歷)、映象翻轉、層次遍歷二叉樹
- 二叉樹迭代器(中序遞迴、前序和後序遍歷)演算法二叉樹遞迴演算法
- 用數學歸納法證明前序序列和中序序列唯一的確定一個二叉樹序列二叉樹
- 【二叉樹】前中序求後序,中後序求前序二叉樹
- 根據二叉樹的先序序列和中序序列還原二叉樹並列印後序序列二叉樹
- 二叉樹 ---- 前序 中序 後序 知二求一二叉樹
- 演算法學習記錄十四(C++)--->二叉樹的映象演算法C++二叉樹
- 從前序與中序構造二叉樹二叉樹
- 二叉樹的前序、中序、後序的遞迴和迭代實現二叉樹遞迴
- 二叉樹的前序、中序、後序三種遍歷二叉樹
- 【樹01】對二叉樹前序/中序/後序遍歷演算法的一些思考二叉樹演算法
- 先序、中序、後序序列的二叉樹構造演算法二叉樹演算法
- 根據二叉樹的前序遍歷和中序遍歷輸出二叉樹;二叉樹
- 劍指offer:輸入某二叉樹的前序遍歷和中序遍歷的結果,請重建出該二叉樹。二叉樹
- 二叉樹的前序,中序,後序遍歷方法總結二叉樹
- LintCode 前序遍歷和中序遍歷樹構造二叉樹二叉樹
- 【資料結構與演算法】二叉樹的 Morris 遍歷(前序、中序、後序)資料結構演算法二叉樹
- LeetCode 105. 從前序與中序遍歷序列構造二叉樹LeetCode二叉樹
- LeetCode-105-從前序與中序遍歷序列構造二叉樹LeetCode二叉樹
- 由中序序列和先序序列確定一顆二叉樹二叉樹
- 後序+中序(前序+中序)重構樹,嚴格O(N)演算法演算法
- 刷題筆記:樹的前序、中序、後序遍歷筆記
- 二叉樹建立,前序遍歷,中序遍歷,後序遍歷 思路二叉樹
- 二叉樹的建立、前序遍歷、中序遍歷、後序遍歷二叉樹
- 【根據前序和中序遍歷構造二叉樹】棧+迭代 || 遞迴二叉樹遞迴
- LeetCode 105. 從前序與中序遍歷序列構造二叉樹 | PytLeetCode二叉樹
- 144. 二叉樹的遍歷「前序、中序、後序」 Golang實現二叉樹Golang
- 【演算法】二叉樹、N叉樹先序、中序、後序、BFS、DFS遍歷的遞迴和迭代實現記錄(Java版)演算法二叉樹遞迴Java
- 資料結構與演算法——二叉樹的前序遍歷,中序遍歷,後序遍歷資料結構演算法二叉樹
- 劍指offer(四)重建二叉樹二叉樹
- 演算法 -- 實現二叉樹先序,中序和後序遍歷演算法二叉樹
- 889. 根據前序和後序遍歷構造二叉樹二叉樹
- 從中序與後序遍歷序列構造二叉樹二叉樹
- 二叉樹前序、中序、後序遍歷相互求法(code留著看,概念先看了)二叉樹
- 144.二叉樹的前序遍歷145.二叉樹的後序遍歷 94.二叉樹的中序遍歷二叉樹