折纸问题与二叉树

来源:互联网 发布:游戏音效增强软件 编辑:程序博客网 时间:2024/05/16 19:33


【题目】

请把纸条竖着放在桌⼦上,然后从纸条的下边向上⽅对折,压出折痕后再展 开。此时有1条折痕,突起的⽅向指向纸条的背⾯,这条折痕叫做“下”折痕 ;突起的⽅向指向纸条正⾯的折痕叫做“上”折痕。如果每次都从下边向上⽅ 对折,对折N次。请从上到下计算出所有折痕的⽅向。
给定折的次数n,请返回从上到下的折痕的数组,若为下折痕则对应元素为"down",若为上折痕则为"up".
测试样例:
1
返回:["down"]


【分析】

实际操作后,发现折纸两次的结果是下下上,多次折纸实际上是一棵二叉树。如图,就是两次折叠结果。


所以,由于在纸上看折痕都是下下上这样的顺序,所以多次折叠实际上就是二叉树右-中-左的遍历。但这道题没有提供二叉树,我们也不可能为这样一个小问题去create一个二叉树。那就用数组吧。

但是,使用数组的递归是很有技巧的,先看代码:


【代码】

class FoldPaper {public:    vector<string> foldPaper(int n) {    vector<string> res;        fold_detail(1, n, true, res);        return res;    }private:    void fold_detail(int i, const int N, bool down, vector<string>& res){        if(i > N)            return;        fold_detail(i+1, N, true, res);        res.push_back(down ? "down" : "up");        fold_detail(i+1, N, false, res);    }};

我们使用i>N来控制循环条件,实际上递归在局部看来更简单。


此图N=2

i=2时会首先以true的形式调用fold_detail(i+1, N, true, res),结果i=3>N返回,然后会继续执行,打印一个“down”。i仍然等于2,再次以false形式调用,>N后返回但是不打印

然后递归回去i=1,此时以ture形式再次调用第一个fold_detail(),i+1=2<3,返回自然打印down。接下来继续执行,以false形式,同样满足i+1=2<3,所以返回时会打印“up"。


现在分析,这其实就是数组右中左遍历二叉树!第一次fold_detail(true)执行完打印"down“,此时必然是右。第二次fold_detail(false),此时理应是左,但是我们要的是右-中-左,所以不打印!然后下一步回到根,在次重复一遍过程,先fold_detail(true),打印”down,此时就是中,即根。然后再次调用fold_detail(i+1,N, false, RES),+1后不会超过N,所以会打印,此时就是”up"了!


局部如此,放大后也是如此!






0 0