二叉树7:折纸练习题

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

思路:对于这种实际问题,动手这一下来找规律:

n=1:下

n=2:下 下 上

n=3:下 下 上 下 下 上 上

n=4:下 下 上 下 下 上 上 下 下 下 上 上 下 上 上

……可以发现是如果建立一棵二叉树,令根结点为下,之后每个结点的左结点为下,右结点为上,那么折痕的顺序恰好就是中序序遍历这棵二叉树的顺序,因此先建立一棵具有上下值的二叉树,然后按照中序遍历的顺序遍历这棵二叉树即可。

首先建立二叉树:显然这是一棵满二叉树,n就是这棵树的层数,按层遍历的方式建立起一棵二叉树,使用一个队列,不需要考虑换行,先将root放入到queue中,然后弹出temp,并为其建立左右结点并分别放入queue中,再弹出一个结点……根据规律,当弹出2^(n-1)-1个结点时恰好将全部结点建立并放入到队列中,于是返回的root结点就是新建二叉树的根结点。

之后使用中序遍历的方式遍历这棵二叉树并将每个结点的值放入到String[]即可。

上面的办法当然可行,但是需要建立二叉树比较麻烦,其实由于这道题目比较特殊,每个结点的子节点之后2个值down和up而且左结点必然是down,右结点必然是up,因此其实不需要建立二叉树就可以直接进行遍历,根结点的值直接给定为true或者false,显然要进行的是对一棵二叉树的中序遍历,建立一个递归函数,实现的功能逻辑是:传入根结点的值和根结点所在的层数,要求中序遍历这棵树。对于一个结点root所在的树,要中序遍历这棵树就要先遍历它的左子树,然后遍历这个根结点(将其放入字符串数组string[]),然后再遍历这个结点的右子树。如何遍历左右子树?由于这里没有建立树的结构,于是递推关系是通过层数来建立的,每一次遍历一棵子树时要给定这棵子树的层数level,初始时root结点的level=1;然后递推关系中,它的左子树的层数就是level+1,根结点的值是down,右子树的层数就是level+1,根结点的值就是up,一直递归调用,当level==对折次数n时遍历结束。

这里关键是构造出一个递归的逻辑,递归的逻辑要求完善而严谨,多练多理解。

常识:key1:集合可以使用toArray()方法直接转换为Object[]类型的数组或者使用toArray(T[])转换为指定类型的数组,但是注意,T[]只能是包装类型的数组,即只能是对象类型的数组String[],Integer[],不能是基本类型的数组int[],否则无法转换。本题中是要求转换为String[]数组因此是可以进行转换的。其实这个原理就是数组类型强制转换的原理,Object[]数组可以强转为(Integer[])objects,但是不能转换为int[] ints=(int[])objects;因此遇到集合转换为String[]的问题可以直接使用toArray()进行转换,但是遇到转换为int[]的不能使用toArray(因为这样只能转换为Integer[]),需要遍历集合逐个取出赋值给数组。但是为了统一,还是选择逐个取出集合中的元素赋值给数组中的元素。

import java.util.*;
//折纸打印问题:利用中序遍历的思想,关键是构造出一个正确的递归函数
public class FoldPaper {
    public String[] foldPaper(int n) {
        //特殊输入
        if(n<1) return null;
        //由于折痕条数不知道所以使用集合(其实折痕条目是知道的)
        List<String> list=new ArrayList<>();
        //调用递归函数getFolder()来返回所有的折痕
        this.getFolder(1,n,"down",list);
        	//key1:将list中的结果逐一取出放入到String[]中,因为list<Integer>不能直接转int[],但是			List<String>可以转String[]
        //但是为了统一,还是使用遍历集合的方式逐个取出
        String[] results=new String[list.size()];
        for(int i=0;i<results.length;i++){
            results[i]=(String)(list.get(i));
        }
        return results;
    }
 //设计一个递归方法,用于对给定层次上指定根结点开始的子树进行中序遍历,将遍历的结点放入list中
 //level:当前遍历的子树根结点的层数;n:最大层数,即对折次数;val:当前子树根结点的值
    private void getFolder(int level,int n,String val,List<String> list){
        //边界条件
        if(level>n) return;
        //①先遍历左子树
        this.getFolder(level+1,n,"down",list);
        //②遍历中间结点(这里的所谓遍历是指将其放入到集合list中)
        list.add(val);
        //③遍历右子树
        this.getFolder(level+1,n,"up",list);
    }
}



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
(1)非递归定义 树(tree)是由n(n≥0)个结点组成的有限集合。n=0的树称为空树;n>0的树T: ① 有且仅有一个结点n0,它没有前驱结点,只有后继结点。n0称作树的根(root)结点。 ② 除结点外n0 , 其余的每一个结点都有且仅有一个直接前驱结点;有零个或多个直接后继结点。 (2)递归定义 一颗大树分成几个大的分枝,每个大分枝再分成几个小分枝,小分枝再分成更小的分枝,… ,每个分枝也都是一颗树,由此我们可以给出树的递归定义。 树(tree)是由n(n≥0)个结点组成的有限集合。n=0的树称为空树;n>0的树T: ① 有且仅有一个结点n0,它没有前驱结点,只有后继结点。n0称作树的根(root)结点。 ② 除根结点之外的其他结点分为m(m≥0)个互不相交的集合T0,T1,…,Tm-1,其中每个集合Ti(0≤i<m)本身又是一棵树,称为根的子树(subtree)。 2、掌握树的各种术语: (1) 父母、孩子与兄弟结点 (2) 度 (3) 结点层次、树的高度 (4) 边、路径 (5) 无序树、有序树 (6) 森林 3、二叉树的定义 二叉树(binary tree)是由n(n≥0)个结点组成的有限集合,此集合或者为空,或者由一个根结点加上两棵分别称为左、右子树的,互不相交的二叉树组成。 二叉树可以为空集,因此根可以有空的左子树或者右子树,亦或者左、右子树皆为空。 4、掌握二叉树的五个性质 5、二叉树的二叉链表存储。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值