高能预警:此文作者水平极差,漏洞百出,错误俯拾皆是,行文毫无逻辑!此文仅供作者自己研究所用。
不得不承认,刘汝佳老师实在是太厉害了(或许是因为我太弱鸡了、、、)
个人认为,最好理解这段代码的方式是这样:以题目给出的样例输入和图为例。递归函数有这样的性质:子函数没有结束之前,母函数是不会结束的。借用刘汝佳老师在紫书(P.77)中举得例子:知府还不知道今年收了多少粮食,皇帝怎么可能知道?也就是说,母函数中代码会有一部分只到子函数代码执行完毕后才执行,那么分界线在哪儿呢?就在第8行和第9行之间。我们可以按照题目中给出的样例不停地去制造子天平,只到真正给出一个个砝码的时候,当砝码被一个个给出,再去运行每个函数中的第9和第10行代码。(有点拗口,水平实在有限,求原谅,如果不原谅,请看本文开头的高能预警)正因为如此,主函数中声明的w有没有赋值是无所谓的,因为它总会被后来的值修改、覆盖。
另外,先序遍历的运算顺序是先沿左侧连进行,然后把左侧连末端的兄弟(也就是左侧连末端的父亲的右孩子)推进栈中,然后运行,参见邓俊辉老师的数据结构:http://www.xuetangx.com/courses/course-v1:TsinghuaX+30240184+sp/courseware/16d8402a24fd4429a8a7cc1c8401cb1f/ee9506a84ba64005a06aa6dc4773f27b/
另外,不妨温习一下刘老师给出的唯一注释:输入一个子天平,返回天平是否平衡,参数w修改为子天平的重量。
输入的是四个整数,返回的是布尔值,还修改了一个整数,amazing!
#include<iostream>
using namespace std;
bool solve(int& w) {
int w1, d1, w2, d2;
bool b1 = true, b2 = true;
cin >> w1 >> d1 >> w2 >> d2;
if(!w1) b1 = solve(w1);
if(!w2) b2 = solve(w2);
w = w1 + w2;
return b1 && b2 && (w1 + d1 == w2 + d2);
}
int main() {
int t,w;
cin >> t;
while(t--) {
if(solve(w)) cout << "YES\n"; else cout << "NO\n";
if(t) cout << "\n";
}
return 0;
}
以下是没用的废话:
另外,个人认为,能把这个题和二叉树的先序遍历联系到一起也很不容易,个人的体会如下:
1、透过一些共有的、关键词汇,比如sub-mobile子天平,联系到二叉树中的左右孩子
2、数据结构是算法中很重要的一部分,所以对于题目,除了重视它的数据之外,还要看到它的结构
3、要学会去掉其复杂的背景,抽象出本质
4、利用所给的图,不妨把图重新画一下。
问题分解:
1、输入:可以以stringstream的形式来保存之。可是如何把递归给出的(先序遍历序列)给还原成一棵二叉树呢?(根本不需要建树,在输入的过程中就直接判断了,太厉害了!)
2、处理:就是判断它是否平衡呗
3、输出:设置一个全局变量
根节点的值可以用来判断是否平衡
难点:如何建树?以何种方式建树?
如果你只知道要用递归,但是不知道如何架构起递归,那么就强行在函数中重新用这个函数。这也是一种不得已而为之的方法。