原方法出自
http://blog.csdn.net/liaozelin_/article/details/78495589
LeetCode 105
题意:给出先序遍历和中序遍历的结果,求整棵树的原貌。
思路:1、前序遍历结果的第一个元素必是根节点
2、在中序遍历结果中找到前序遍历的第一个元素,该元素的左侧为左子树集合,右侧为右子树集合。
3、递归
#include "stdafx.h"
#include<iostream>
#include<vector>
using namespace std;
struct TreeNode {
int val;
TreeNode *left;
TreeNode *right;
TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
};
//函数声明
TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder);
TreeNode* driver(vector<int>& preorder, vector<int>& inorder, int p_lo, int p_hi, int i_lo, int i_hi);
int find(vector<int>& vec, int low, int high, int val);
TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
//调用函数返回完整的树
return driver(preorder, inorder, 0, preorder.size() - 1, 0, inorder.size() - 1);
}
TreeNode* driver(vector<int>& preorder, vector<int>& inorder, int p_lo, int p_hi, int i_lo, int i_hi) {
// 递归的边界,子树为空或着只有一个结点
if (p_lo > p_hi) return NULL;
if (p_lo == p_hi) return new TreeNode(preorder[p_lo]);
//获取该节点的价值
int node_val = preorder[p_lo];
//获取该节点在中序遍历序列中的位置
int index_in = find(inorder, i_lo, i_hi, node_val);
//前序遍历序列中,该节点的左子树集合大小
int pre_left_len = index_in - i_lo;
TreeNode* node = new TreeNode(node_val);
// preorder[p_lo+1 ... p_lo+pre_left_len]是先序数组中与现结点左子树对应的部分。
// inorder[i_lo ... index_in-1]是中序数组中与现结点左子树对应的部分。
node->left = driver(preorder, inorder, p_lo + 1, p_lo + pre_left_len, i_lo, index_in - 1);
// preorder[ p_lo + pre_left_len + 1 ... p_hi]是先序数组中与现结点右子树对应的部分。
// inorder[index_in + 1 ... i_hi]是中序数组中与现结点右子树对应的部分。
node->right = driver(preorder, inorder, p_lo + pre_left_len + 1, p_hi, index_in + 1, i_hi);
return node;
}
//找当前节点在中序遍历序列中的索引位置
int find(vector<int>& vec, int low, int high, int val) {
for (int i = low; i <= high; ++i) {
if (vec[i] == val) return i;
}
return -1;
}
int main()
{
vector<int> preorder = { 3,9,20,15,7 };
vector<int>inorder = { 9,3,15,20,7 };
//vector<int>num = { 3,9,20,-1,-1,15,7 };
//TreeNode* answer=CreatTree(num);
TreeNode* answer = buildTree(preorder, inorder);
return 0;
}
LeetCode 106
题意:给中序和后续遍历,求整棵树。
思路:后序遍历序列最后一个元素为根节点,找该点在前序遍历中的索引位置。该点在前序遍历中左侧为左子树集合,右侧为右子树集合。
#include "stdafx.h"
#include<iostream>
#include<vector>
using namespace std;
struct TreeNode {
int val;
TreeNode *left;
TreeNode *right;
TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
};
//函数声明
TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder);
TreeNode* driver(vector<int>& preorder, vector<int>& inorder, int p_lo, int p_hi, int i_lo, int i_hi);
int find(vector<int>& vec, int low, int high, int val);
TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
return driver(postorder, inorder, 0, postorder.size() - 1, 0, inorder.size() - 1);
}
TreeNode* driver(vector<int>& postorder, vector<int>& inorder, int p_lo, int p_hi, int i_lo, int i_hi) {
if (p_lo > p_hi) return nullptr;
if (p_lo == p_hi) return new TreeNode(postorder[p_hi]);
//获取后序遍历序列最后一个元素的值
int node_val = postorder[p_hi];
//获取后序遍历最后一个元素在前序遍历序列中的索引位置
int index_in =find(inorder, i_lo, i_hi, node_val);
//该点的左子树集合大小为pre_left_len
int pre_left_len = index_in - i_lo;
TreeNode* node = new TreeNode(node_val);
// preorder[p_lo ... p_lo + pre_left_len - 1]是中序数组中与现结点左子树对应的部分。
// inorder[i_lo ... index_in - 1]是后续数组中与现结点左子树对应的部分。
node->left = driver(postorder, inorder, p_lo, p_lo + pre_left_len - 1, i_lo, index_in - 1);
// preorder[p_lo + pre_left_len ... p_hi - 1]是中序数组中与现结点左子树对应的部分。
// inorder[index_in + 1 ... i_hi]是后续数组中与现结点左子树对应的部分。
node->right = driver(postorder, inorder, p_lo + pre_left_len, p_hi - 1, index_in + 1, i_hi);
return node;
}
int find(vector<int>& vec, int low, int high, int val) {
for (int i = low; i <= high; ++i) {
if (vec[i] == val) return i;
}
return -1;
}
int main()
{
vector<int> preorder = { 9,3,15,20,7 };
vector<int>inorder = { 9,15,7,20,3 };
TreeNode* answer = buildTree(preorder, inorder);
return 0;
}
LeetCode 129
深度遍历的题,不难,具体实现代码如下:
#include "stdafx.h"
#include<iostream>
#include<vector>
#include<queue>
using namespace std;
struct TreeNode {
int val;
TreeNode *left;
TreeNode *right;
TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
};
//构造二叉树
TreeNode* CreatTree(vector<int>&nums) {
size_t length = nums.size();
if (length == 0) return nullptr;
int index = 0;
TreeNode* root = new TreeNode(nums[index]);
index++;
TreeNode* p = nullptr;
queue<TreeNode*>trans;
trans.push(root);
while (!trans.empty() && index < length) {
p = trans.front();
trans.pop();
if (index < length && nums[index] != -1) {
TreeNode *LeftNode = new TreeNode(nums[index]);
p->left = LeftNode;
trans.push(LeftNode);
}
index++;
if (index < length && nums[index] != -1) {
TreeNode *RightNode = new TreeNode(nums[index]);
p->right = RightNode;
trans.push(RightNode);
}
index++;
}
return root;
}
//递归,将每一支路上的总和加到sum中。这里sum传引用,为了修改sum的值
void solve(TreeNode* root, int cur,int& sum) {
if (!root)
return;
//当遍历到的节点是叶子结点时
if (root->left == NULL && root->right == NULL) {
cur = cur * 10 + root->val;
sum += cur;
return;
}
//非叶子结点,把之前累积的值乘以10与当前节点的值相加,传值到下一次递归
solve(root->left, cur * 10 + root->val, sum);
solve(root->right, cur * 10 + root->val, sum);
}
int sumNumbers(TreeNode* root) {
//当root为空,说明树是空的
if (!root)
return 0;
int sum = 0;
solve(root, 0, sum);
return sum;
}
int main()
{
vector<int>nums = { 3,5,1,6,2,0,8,-1,-1,7,4,-1,-1,-1,-1 };
TreeNode* root = CreatTree(nums);
int answer = sumNumbers(root);
return 0;
}