43行代码AC——例题6-8 树(Tree,UVa 548)——解题报告

励志用尽量少的代码做高效的表达。


题目大意

给定二叉树的中序和后序遍历序列,求该二叉树中根到叶子的路径和最小者,若存在多个解,则选择叶子权值最小者(叶子权值不重复)。

思路分析

此题本质是中后序建树+求路径最小权。
(PS:书上的数组建树用不习惯,于是自己写了一个指针建树。)
关键在于中序和后序建树,后序遍历序列的最后一个元素来确定根(前序的话是第一个元素确定根),中序序列来划分左右子树,如此递归建立树
对于路径和求解,建树完成后对树进行dfs

#include<bits/stdc++.h> 
using namespace std;
struct Node {
	int v;							//值
	Node *l = NULL, *r = NULL;		//左右子树 
};
vector<int> in, post;				//中序,后序存储
int minsum = 0x3fffff, ans = -1;	//路径最小和、答案(叶子节点) 
Node* createTree(int i1, int j1, int i2, int j2) {
	if(i1 >= j1 || i2 >= j2) return NULL;		//空树
	Node* root = new Node;
	root->v = post[j2-1];			//根节点为后续遍历最后一个数
	int j = find(in.begin()+i1, in.begin()+j1, post[j2-1]) - in.begin();//在中序遍历中查找该值
	root->l = createTree(i1, j, i2, i2+(j-i1));		//建立左子树
	root->r = createTree(j+1, j1, i2+(j-i1), j2-1);	//建立右子树
	return root; 
} 
void dfs(Node* root, int sum) {		//计算到每个叶子的路径和并记录最小者
	if(root->l == NULL && root->r == NULL) {		//判断是否遍历到头 
		sum += root->v;
		if(sum < minsum || (sum == minsum && ans > root->v)) {
			minsum = sum;
			ans = root->v; 
		} 
		return;
	}
	if(root->l != NULL) dfs(root->l, root->v+sum);	//非空,则访问左子树
	if(root->r != NULL) dfs(root->r, root->v+sum);	//非空,则访问右子树 
}
int main() {
	string s1, s2;
	int s;
	while(getline(cin, s1) && getline(cin, s2)) {
		in.clear(); post.clear();					//初始化
		stringstream input1(s1), input2(s2);
		while(input1 >> s) in.push_back(s);
		while(input2 >> s) post.push_back(s);
		Node* btree = createTree(0, in.size(), 0, post.size());	//建树
		minsum = 0x3fffff; dfs(btree, 0);			//遍历计算
		printf("%d\n", ans); 
	}
	return 0;
} 

收获:

1、巩固了DFS
2、掌握了中后序遍历建树。
3、掌握了求最小权路径的方法。


择苦而安,择做而乐,虚拟现实终究比不过真实精彩之万一。

发布了97 篇原创文章 · 获赞 104 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/weixin_43899069/article/details/104880496