/*
买票找零:
每张球票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个符号与第一个符号一定匹配,所以合法括号序列
编程之美:第四章 数字之趣 4.3买票找零
最新推荐文章于 2016-10-15 12:51:20 发布