编程之美:第四章 数字之趣 4.3买票找零

/*
买票找零:
每张球票50元,现有2*n个人排队购票,其中有n个人手持50元的钞票,另外n个人手持100元的钞票,假设开始售票时没有零钱找。问这2*n个人有多少种排队方式,
不至于售票处出现找不开钱的局面?

注意至少要保证排在前面的持50元的人数>=持100元的人数

解法1:
从队首往后数,手持100元的球迷总比手持50元的球迷少,可以把钱召开。
联想到括号匹配问题。假设每个手持50元的球迷是一个左括号"(",而手持100元的球迷是一个右括号")",任意一个售出100元的球迷找回的50元都来自于之前一个
手持50元的球迷
用栈,遍历n个左括号和n个右括号,如果是左括号,则压栈中,如果是右括号,那么让栈顶的左括号出栈,如果始终能够保持栈中有足够的左括号,那么是一个合法
排列。

第0个符号一定是左括号,假设第0个左括号与第k个符号匹配,那么从第一个符号到第(k-1)个符号,第(k+1)个符号到第2n-1个符号也都是一个合法的括号序列。
而k肯定是奇数,否则第1个符号到第(k-1)个符号之间只有奇数个符号就不合法,设k = 2*i+1 (i = 0,1,...,n-1)

0 1 .... 2i 2i+1 2i+2 ... 2n-1
  ________       _____________
    2i个            2n-2i-2个
假设2n个符号中合法的括号序列个数为f(2n),若第0个括号(左括号)与第k=2i+1(i = 01,2,...,n-1)个括号(右括号)匹配,那么剩余括号的合法序列为:
f(2*i) * f(2*n-2*i-2)
得到递推式:
f(2n) = i从0到n-1 对f(2i)*f(2n-2i-2)累加排列数
      = [f(0)*f(2n-2)] + [f(2)*f(2n-4)] + [f(4)*f(2n-6)] + ... + [f(2n-2)*f(0)]
	  其中f(0) = 1,可以用O(n*m)的时间求出问题答案。f(0) = f(2*0) = 0个符号中合法的括号序列个数为1 ? 第0个符号一定是左括号,由于中间没有间隔元素,
	  第0个符号与第一个符号一定匹配,所以合法括号序列
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值