本篇同步發布於Blog: [解題] UVa - 548 Tree
UVa Online Judge
548 - Tree
給一個樹的中序(Inorder)和後序(Postorder),求這個樹的葉子到根的值總和是最小的路徑,並輸出那路徑的葉子值。假如有多個路徑的總和最小值相同,則輸出葉子值是最小的。
樹的節點最多會有10000個、最少1個。
3 2 1 4 5 7 6
3 1 2 5 6 7 4
7 8 11 3 5 16 12 18
8 3 11 7 16 18 12 5
255
255
1
3
255
經典的樹狀資料結構問題,首先要將後序與中序的關係釐清,並建立原來的樹,即可用深度搜尋去找路徑。
以下用畫圖解釋第1個範例輸入,原始的中序與後序如圖1

圖1
目前後序的最右邊值,為目前的根,也就是4,對應到中序,可區分左子樹與右子樹的範圍,如圖2。接著我們往左子樹遞迴找子節點。
圖2
4節點的左子樹範圍,2的後序索引值是最大的,所以2是連著4的節點,在中序又可區分左子樹與右子樹的範圍,如圖3。

圖3
2的左子樹與右子樹再遞迴處理後是3和1,如圖4與圖5。
圖4
圖5
4節點的右子樹範圍,7的後序索引值是最大的,所以7是連著4的節點,在中序又可區分左子樹與右子樹的範圍,如圖6。
圖6
7的左子樹與右子樹再遞迴處理後是5和6,如圖7與圖8。
圖7
圖8
最終答案是(4 + 2 + 1)的路徑總和是最小的 ,於是輸出這路徑的節點1。
而程式碼使用遞迴的方式解析中序和後序,再用Linked List建立樹。
難度為Medium
#include <iostream>
#include <string>
#include <sstream>
#include <map>
using namespace std;
map<int, int> inorderMapIndex;
int postorderNodes[10005];
int inorderNodes[10005];
int ans;
int ans_sums;
struct TreeNode{
	TreeNode* left;
	TreeNode* right;
	int val;
	TreeNode(){};
	TreeNode(int initVal)
	{
		val = initVal;
		left = NULL;
		right = NULL;
	}
};
TreeNode* parseNodes(int L1, int R1, int L2, int R2){
	if(L1 > R1){
		return NULL;
	}
	
	int inorderIndex = inorderMapIndex[postorderNodes[R2]];
	int leftCounts = inorderIndex - L1;
	TreeNode* curParent = new TreeNode(postorderNodes[R2]);
	curParent->left = parseNodes(L1, inorderIndex-1, L2, L2 + leftCounts - 1);
	curParent->right = parseNodes(inorderIndex + 1, R1, L2 + leftCounts, R2 - 1);
	
	return curParent;
}
void findLeastVal(TreeNode* node, int sum){
	if(node == NULL)
		return;
	
	sum += node->val;
	
	findLeastVal(node->left, sum);
	findLeastVal(node->right, sum);
	
	if(node->left == NULL && node->right == NULL){
		if(sum < ans_sums || (sum == ans_sums && ans > node->val)){
			ans = node->val;
			ans_sums = sum;
		}
	}
	
}
int main() 
{
    string s;
	while(getline(cin, s)){
		inorderMapIndex.clear();
		int curVal;
		int totalLength = 0;
		
		stringstream ss1(s);
		while(ss1 >> curVal){
			inorderMapIndex[curVal] = totalLength;
			inorderNodes[totalLength] = curVal;
			totalLength++;
		}
		
		totalLength = 0;
		getline(cin, s);
		stringstream ss2(s);
		while(ss2 >> curVal){
			postorderNodes[totalLength] = curVal;
			totalLength++;
		}
		
		TreeNode* root = parseNodes(0, totalLength-1, 0, totalLength-1);
		
		ans_sums = 999999999;
		findLeastVal(root, 0);
		
		cout << ans << endl;
	}
    return 0;
}
https://github.com/u8989332/ProblemSolving/blob/master/UVaOnlineJudge/500-599/548.cpp