548 - Tree(UPDATE)

原解法: 548 - Tree

改进: 不建树, 而是在建树的过程中把根节点到各个叶节点的和都算出来, 因为建树的时候就是一个由顶到下的过程, 所以是可以把这段路径上的和给算出来的使用一个全局 pair 存放最小的和, 每算出一个和, 就与全局的 pair 相比, 若比当前小, 则替换当前全局 pair, 最后再输出这个 pair 的叶子节点值即可.

要点:
1. numeric_limits<int>::max(); // <limits> 获取 int 最大值.

题目:
http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=104&page=show_problem&problem=489

代码:

# include <iostream>
# include <string>
# include <cstdio>
# include <cstring>
# include <vector>
# include <algorithm>
# include <cctype>
# include <iterator>
# include <sstream>
# include <assert.h>
# include <limits>
using namespace std;


// 不建树, 而是在建树的过程中把根节点到各个叶节点的和都算出来
// 使用一个全局 pair 存放最小的和


// 记录当前最小和, first 为和, second 为叶子节点值
pair<int, int> MIN_SUM;

void setToMinSum(int sum, int nodeValue) {
  if ( sum < MIN_SUM.first ||
      (sum == MIN_SUM.first && nodeValue < MIN_SUM.second)) {
    MIN_SUM = make_pair(sum, nodeValue);
  } 
}

// 找到 n 在 vt[begin, end) 中的下标,若找不到,则返回 end
// 为了保证重复节点出现时,找到的下标是靠后的节点,这里从后往前找
int getIndex(const vector<int>& vt, int begin, int end, int n) {
  for (int i=end-1; i>=begin; i--) {
    if (vt[i] == n) return i;
  }
  return end;
}

// 根据中序与后序遍历创建树
// 中序:左根右
// 后序:左右根
// 算法:由上可以看到,从后序最后开始遍历,找到“根”,然后在中序中找到“根”,
// 其左边就是左子树,右边就是右子树
// 针对中序遍历 inOrder[inBegin, inEnd) 中的部分建树
//    后序遍历 postOrder[inBegin, inEnd) 中的部分建树
void buildTree(const vector<int>& inOrder, int inBegin, int inEnd,
               const vector<int>& postOrder, int postBegin, int postEnd,
               int sum) {
  if (inEnd - inBegin == 1) {
    int root = postOrder[postBegin];
    setToMinSum(sum + root, root);
    return;
  }

  if (inEnd - inBegin <= 0) return;

  // 后序的最后一位就是根节点
  int root = postOrder[postEnd-1];
  int rootIndex = getIndex(inOrder, inBegin, inEnd, root);
  int leftLength = rootIndex - inBegin;

  buildTree(inOrder, inBegin, rootIndex,
            postOrder, postBegin, postBegin + leftLength,
            sum + root);

  buildTree(inOrder, rootIndex + 1, inEnd,
            postOrder, postBegin + leftLength, postEnd - 1,
            sum + root);
}


int main(int argc, char const *argv[])
{
  #ifndef ONLINE_JUDGE
    freopen("548_i.txt", "r", stdin);  
    freopen("uva_o.txt", "w", stdout); 
  #endif
  
  // 输入
  string inLine;
  string postLine;
  while (getline(cin, inLine) && getline(cin, postLine)) {
    MIN_SUM.first  = numeric_limits<int>::max(); 
    MIN_SUM.second = numeric_limits<int>::max();
    
    int n;
    vector<int> inOrder, postOrder;

    // 读取一行中的各个 int
    istringstream issIn(inLine);
    while (issIn >> n) inOrder.push_back(n);
    
    istringstream issPost(postLine);
    while (issPost >> n) postOrder.push_back(n);

    // 建树,分析,输出
    buildTree(inOrder, 0, inOrder.size(),
              postOrder, 0, postOrder.size(),
              0);
 
    cout << MIN_SUM.second << endl;
  }

  return 0;
}
环境:  C++ 4.5.3 - GNU C++ Compiler with options: -lm -lcrypt -O2 -pipe -DONLINE_JUDGE

你可能感兴趣的:(tree,update,uva,548)