uva112 Tree Summing(二叉树 + 栈)

该博客讨论了如何解决UVA112问题,即利用LISP列表语言表示的二叉树,寻找一条路径,其节点之和等于给定的目标值。通过栈来跟踪路径,当遇到叶子节点时,比较当前路径和目标值,如果相等则返回'yes',否则返回'no'。输入处理是难点,使用getchar逐字符读取,遇到数字部分存储并使用sscanf解析。算法的时间复杂度为O(n),其中n为字符数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题意:LISP 列表语言实现二叉树, 构树方式对照图就可知道,  叶子后面都有两个()。 给定一个数target, 求此树中是否有一条路径(从root到叶子), 它上面的结点总和等于target, 如果存在 输出yes, 否则输出no。


思路:这道题可以不用建树。只要读到叶子结点的时候, 把这条路的sum 跟 target比较, 相等就ok = true。 如何读? 读到( 入栈staSign, 读到数值, 入栈staNum, 读到)的时候staSign 跟 staNum各出栈(当然情况没那么简单, 如果读入空括号怎么办? 判断两栈的size是否相等。), 用count统计连续读入的空括号数, count == 2 的时候, 自然是到了叶子结点。 这道题 难点还在于输入处理, 用getchar() 一个字符一个字符的读入。遇到数字的组成部分就保存在字符里, 然后sscanf()


算法复杂度:o(n)n是字符数。


代码:

uva112_.cpp AC后重写的。

#include <cstdio>
#include <cstring>
#include <stack>
#include <cctype>
using namespace std;

#define NUM_BIT 100

int main()
{
	int target;
	stack<char> staSign;
	stack<int> staNum;
	bool ok;
	char last;
	int count;
	char strNum[NUM_BIT];
	char *p;

	while (scanf("%d", &target) == 1) {
		// init 
		while (!staSign.empty()) {
			staSign.pop();
		}
		while (!staNum.empty()) {
			staNum.pop();
		}
		ok = false;
		last = '\0';
		count = 0;
		memset(strNum, 0, sizeof(strNum));
		p = strNum;

		// enter tree
		char ch;
		while (ch = getchar()) {
			if (isdigit(ch) || ch == '(' || ch == ')' || ch == '-') {
				if (ch == '(') {
					staSign.push(ch);	
					if (isdigit(last)) {
						int num;
						sscanf(strNum, "%d", &num);
						if (!staNum.empty()) {
							num += staNum.top();
						}
						staNum.push(num);
						memset(strNum, 0, sizeof(strNum));
						p = strNum;
					}
				} else if (isdigit(ch) || ch == '-') {
					*p++ = ch;
					count = 0;
				} else if (ch == ')') {
					if (staNum.size() != staSign.size()) {
						count++;
						if (!staNum.empty() && count == 2 && staNum.top() == target) {
							ok = true;
						}
					} else {
						staNum.pop();
					}

					staSign.pop();
					if (staSign.empty()) {
						break;
					}
				}

				last = ch;
			}
		}

		if (ok) {
			printf("yes\n");
		} else {
			printf("no\n");
		}
	}

	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值