闲聊蓝桥杯JAVA - 出栈次序

出栈次序

D:做一道简单的题目

X星球特别讲究秩序,所有道路都是单行线。
一个甲壳虫车队,共16辆车,按照编号先后发车,夹在其它车流中,缓缓前行。

路边有个死胡同,只能容一辆车通过,是临时的检查站,如图所示。
X星球太死板,要求每辆路过的车必须进入检查站,也可能不检查就放行,也可能仔细检查。
如果车辆进入检查站和离开的次序可以任意交错。那么,该车队再次上路后,可能的次序有多少种?

为了方便起见,假设检查站可容纳任意数量的汽车。
显然,如果车队只有1辆车,可能次序1种;2辆车可能次序2种;3辆车可能次序5种。

这里写图片描述

M:大概题目的意思就是,16辆车都要进栈,但是进栈期间有别的车会出栈,这样车的顺序最后就会改变,问有多少种改变顺序。

Z:这是递归的算法,由于跟顺序无关,所以根本不需用到stack,解法如下:

public class Test {
    public static void main(String[] args) {
        System.out.println(stack(16,0));
    }

    private static int stack(int inStack, int atStack) {  //准备进栈数,出栈数
        if(inStack == 0){
            return 1;
        }
        if(atStack == 0){
            return stack(inStack-1, 1);
        }
        return stack(inStack-1,atStack+1)+stack(inStack, atStack-1);
    }
}   

答案是35357670

M:这道题有点不好理解,怎么想到用进栈和出栈做参数的呢?

Z:因为改变次序的实质就是车辆对栈 进&出。它既是整个流程的大体描述,也可以细化到每一小步的单元。

也就是说改变次序的操作就是:放进去+拿出来。而题目的已知量是 总数=16,所以要通过总数描述放进去+拿出来 的操作,就需要引入 栈中数 这个变量。

M:那怎么考虑到这条递归式子的呢?

Z:还是这道题目的 放进去+拿出来 核心要点,描述一个步骤(总数-1,栈中数+1)=放进去(总数不变,栈中数-1)=拿出来。这两种情况加起来,就等于16辆车的所有排序情况。

M:那这个出口是怎么定的呢?

        if(inStack == 0){
            return 1;
        }
        if(atStack == 0){
            return stack(inStack-1, 1);
        }

Z:那就是对参数的考察,inStack和atStack会不断减少,而atStack会不断增多。但是减少不能少于0,所以需要给inStack和atStack设置为0的返回情况。

inStack:当要进去的车所有都进去了,那就只剩下拿出来1种操作了,所以出来的只有1种情况,返回1。

atStack:当出来的车所有都出来了,那就只剩下拿进去1种操作了,所以执行最小单位的拿进去操作stack(inStack-1, 1)

而因为atStack增多一个,inStack就减少一个,只要对其中一者进行了限制,另一个也就不需要进行限制了。

M:递归是一个很神奇的东西,它不需要知道过程的每一步详细步骤。只要设定一个规则,再设定一个限定出口,程序就会将所有符合的规则走一遍。

一般遇到这种规则模拟的题目,就可以考虑到使用递归。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值