题意:
题目要求很简单,意思是要构造一颗二叉树,然后求出所有根结点到叶结点的路径上的数字之和,如果有一个是和题目所给的一样,那么输出yes,否则no
左括号‘(' 表示新建一个子结点, 优先建立左儿子,如果左儿子建立过了,则建立右儿子。 右括号表示退回父结点。如果一对括号内是空的,表示这个结点
也是空的。
思路:
输入比较复杂, 有括号,有数字,又有空格,于是用getchar()一个一个读, 过滤掉空格,保存到一个数组里。然后再处理。 然后利用栈建二叉树, 进行深搜,得到路径和。
另一个思路比较简单,题目给出的数据本身具备前序遍历的顺序,可以直接算路径和。但是我想熟悉一下建二叉树和深度搜索,所以用的是建树深搜的思路。
PS:下面代码有个小bug,如果只有一个叶子节点的情况下,建的二叉树都会把叶子作为左叶子。但是不影响结果。
//112 - Tree Summing
#include <iostream>
#include <cstring>
#include <stack>
using namespace std;
struct Nobe
{
int value;
Nobe *left = NULL, *right = NULL;
bool haveleft = false;//判断是否已有右节点
};
char str[5200];
void DFS(Nobe *, int, int);
bool found;
int main()
{
freopen("data.txt", "r", stdin);
int sum;
while (scanf("%d", &sum) != EOF)
{
int bracket = 0, len = 0;
char c;
while ((c = getchar()) != '(');//跳过前面的空格
str[len++] = c;//
bracket++;
while (bracket)//括号匹配就退出
{
while((c = getchar()) == ' ' || c == '\n');//跳过中间的空格和换行符
if(c == '(')//
bracket++;
if(c == ')')
bracket--;
str[len++] = c;
}
if(str[0] == '(' && str[1] == ')')//如果是空树
{
printf("no\n");
continue;
}
stack<Nobe*> st;
int x;
sscanf(&str[1], "%d", &x);//取出字符串中的数字
Nobe *s = new Nobe;
s->value = x;
Nobe *root = s;//初始化根
st.push(s);
int i = 1;
while (!st.empty())
{
while(str[i] != '(' && str[i] != ')')//跳过数字占用的字符
i++;
if(str[i] == '(' && str[i + 1] != ')')//排除"()"的情况
{
sscanf(&str[++i], "%d", &x);
Nobe *s = new Nobe;
s->value = x;
st.push(s);
}
else if(str[i] == ')' && str[i - 1] != '(')//排除"()"的情况,出栈建树
{
Nobe *p;
p = st.top();
st.pop();
if(!st.empty())
if(!st.top()->haveleft)//
{
st.top()->left = p;
st.top()->haveleft = true;
}
else
st.top()->right = p;
}
i++;
}
found = false;
DFS(root, sum, 0);
if(found)
printf("yes\n");
else
printf("no\n");
memset(str, 0, sizeof(str));
}
return 0;
}
void DFS(Nobe *s, int sum, int n)
{
if(found)
return;
n += s->value;
if(s->left == NULL && s->right == NULL)
{
if(n == sum)
found = true;
return;
}
if(s->left)
DFS(s->left, sum, n);
if(s->right)
DFS(s->right, sum, n);
}