zoukankan      html  css  js  c++  java
  • Tree Summing[UVA-112]

    Tree Summing

    UVA-112 Time Limit:3000ms

    这个题主要还是考察对二叉树的理解,刚看到感觉挺简单的,但是做起来却是一个接着一个坑。

    首先说一下思路吧。最先想到的是重建整个二叉树,然后对整个树遍历,求出所有从树根到叶子的和,再与题目要求的数进行比较。后来一想其实没必要重建整个树,因为在这个题目的输入下,重建整个树的过程就相当于一次DFS,DFS到底实际上就是达到叶子节点了。因此,一边处理输入一边直接计算求和就行了,满足公式:$s_c=s_p+v_c$,其中$s_c$表示从根结点到当前结点的和,$s_p$表示从根结点到父节点的和,$v_c$表示当前结点存储的值。我这里是使用了栈进行非递归的求解,因此对应的栈顶元素就是$s_p$,其实很多解答用了递归也是非常精妙的,看起来非常简洁。

    下面说说细节。第一个就是如何处理输入的问题。一组输入包含换行符和空格,因此fgets()和scanf()都不能用的,包括C++的cin.getline()。所以只能用getchar()来逐个字符读入,碰到不符合要求的就舍去。我这里是先将这个输入序列重新格式化后存储起来,然后调用solve()函数进行求解,实际上直接边读入边处理也是可以的,只是在叶子结点判断上要稍微麻烦一点。对于输入结束,因为题目保证数据合法,因此只要栈空,必然就应该结束当前数据的输入了。第二个是叶子结点的判断。注意题目的描述是,除了空树只包含一堆括号“()”,其余的,只要是叶子节点,必然在叶子节点的值的后面有两对括号(如:“(5()())”),因此要连续判断四个字符是不是一堆括号,来决定是不是叶子结点。对于我这种使用保存了的序列的,比较好操作,直接对数组的连续四个元素判断就行;如果是边读入边处理,那么就需要标志变量了,显然麻烦一些。最后一个坑,就是,输入数据可能包含负数!(虽然题目没给数据范围)。因为这个WA了好几遍,蛋疼。

    最后是我的实现:

     1 #include<cstdio>
     2 #include<queue>
     3 #include<stack>
     4 using namespace std;
     5 char str[500000];
     6 int sum;
     7 int solve(const char * str)
     8 {
     9     if (str[0] == '('&&str[1] == ')')
    10         return 0;
    11     stack<int> st;
    12     int i = 1, val, j = 0;
    13     char buf[11];
    14     for (; str[i] != '('; i++, j++)
    15         buf[j] = str[i];
    16     buf[j] = 0;
    17     sscanf(buf, "%d", &val);
    18     st.push(val);
    19     for (; !st.empty();)
    20     {
    21         if (str[i] == '('&&str[i + 1] == ')')
    22         {
    23             if (str[i + 2] == '('&&str[i + 3] == ')')
    24             {
    25                 if (st.top() == sum)
    26                     return 1;
    27                 i += 4;
    28             }
    29             else
    30                 i += 2;
    31         }
    32         else
    33         {
    34             if (str[i] == '(')
    35             {
    36                 i++;
    37                 for (j = 0; str[i] != '('; i++, j++)
    38                     buf[j] = str[i];
    39                 buf[j] = 0;
    40                 i--;
    41                 sscanf(buf, "%d", &val);
    42                 st.push(st.top() + val);
    43             }
    44             else if (str[i] == ')')
    45                 st.pop();
    46             i++;
    47         }
    48     }
    49     return 0;
    50 }
    51 int main()
    52 {
    53     while (scanf("%d", &sum) != EOF)
    54     {
    55         stack<char> st;
    56         getchar();
    57         char c;
    58         int pos = 0;
    59         for (;;)
    60         {
    61             c = getchar();
    62             if (c == ' '||c == '
    ')
    63                 continue;
    64             str[pos++] = c;
    65             if (c == '(') st.push(c);
    66             else if (c == ')')st.pop();
    67             if (st.empty())break;
    68         }
    69         str[pos] = 0;
    70         if (solve(str))
    71             printf("yes
    ");
    72         else
    73             printf("no
    ");
    74     }
    75     return 0;
    76 }
  • 相关阅读:
    redis可编译
    不要用Serverzoo 提供的CloudLinux 的五大原因 Linode 強大VPS 資源為你解密
    linux加载指定目录的so文件
    超级rtmp服务器和屌丝wowza
    标准IO: 文件的打开与关闭函数 fopen & fclose
    《gdb调试之基础篇》
    linux信号Linux下Signal信号太详细了,终于找到了
    【干货】Chrome插件(扩展)开发全攻略
    斯坦福开源无Bug的随机计算图Certigrad
    心跳包:告诉别人,我还活着
  • 原文地址:https://www.cnblogs.com/ggggg63/p/6906863.html
Copyright © 2011-2022 走看看