折纸问题——递归模拟栈

284 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第12天,点击查看活动详情

请把一段纸条竖着放在桌子上,然后从纸条的下边向上方对折1次,压出折痕后展开。此时折痕是凹下去的,即折痕突起的方向指向纸条的背面。如果从纸条的下边向上方连续对折2次,压出折痕后展开,此时有三条折痕,从上到下依次是下折痕、下折痕和上折痕。 给定一个输入参数N,代表纸条都从下边向上方连续对折N次。请从上到下打印所有折痕的方向。 例如:N=1时,打印: down N=2时,打印: down down up 在这里插入图片描述 不难发现,每次对折后,都有这样一个规律:在已有的折痕上边都是凹折痕,下边都是凸折痕所以从上到下打印所有折痕方向,就是在中序遍历二叉树。

那么需要把这颗树完整建出来吗?对折N次,就会有 N^(2-1)条折痕,然后准备一个长度为 N^(2-1)的数组,再将数组填满,最后再将数组打印出来,这种实现方式巨大的浪费空间,肯定有更优的解决办法——用递归模拟整棵树,因为这颗树有着明确的规则,所以不用把所有结点建出来才能够打印。

  1. 整棵树的头结点是“凹”
  2. 所有左子树的头结点是“凹”,所有右子树头结点是“凸”

这种方式的时间复杂度就是递归栈的代价,O(N)

package com.harrison.class07;

public class Code08_PaperFloding {
	public static void printAllFolds(int N) {
		printProcess(1, N, true);
	}

	// 当前你来了一个节点,脑海中想象的!
	// 这个节点在第i层,一共有N层,N固定不变的
	// 这个节点如果是凹的话,down = T
	// 这个节点如果是凸的话,down = F
	// 函数的功能:中序打印以你想象的节点为头的整棵树!
	public static void printProcess(int i, int N, boolean down) {
		if (i > N) {
			return;
		}
		printProcess(i + 1, N, true);
		System.out.println(down ? "凹" : "凸");
		printProcess(i + 1, N, false);
	}

	public static void main(String[] args) {
		int N = 3;
		printAllFolds(N);
	}
}