【marscode AI刷题】栈—套碗游戏的取碗顺序问题 1 and 2

182 阅读3分钟

进出栈的多样性问题。

1 套碗游戏的取碗顺序问题

问题描述

小F正在玩一个套碗的游戏,每个碗都有一个编号,从1到n,它们从大到小被套在一根木棍上。小F只能从木棍上取最上面的碗,每次只能取一个。现在你需要判断给定的取碗顺序是否可行。如果可行,那么返回1,否则返回0。

例如,对于2个碗,取碗的顺序可以是 2 1 或 1 2,这两种顺序都是合法的。而对于3个碗,给定顺序 3 1 2 不可能通过合法操作实现,因此该顺序不可行。


测试样例

样例1:

输入:M = 2, a = [1, 2]
输出:1

样例2:

输入:M = 3, a = [3, 1, 2]
输出:0

样例3:

输入:M = 4, a = [1, 3, 2, 4]
输出:1

思路

这道题光看题目我是看不懂的,然后琢磨了一下样例,发现其实就是进出栈的多样性的问题。 规定栈一定是从小到大排序。那么1,2,3 三个元素有多种进栈和出栈的可能性,比如1进栈,1出栈,然后23进栈,32出栈,但是不能是3 1 2 的顺序,因为1 2 3依次进栈的话一定是 1进栈,2进栈,3进栈,然后3 2 1出栈。 当3先出栈的时候,21已经在栈里了,这个时候出栈顺序就是2 1而不是1 2.

所以当一个元素出栈时,它之前的元素一定已经全都进栈了。

代码实现

def solution(M: int, a: list) -> int:
    # write code here
    stack = []
    stack_index = 0
    for i in a:
        if stack:
            if stack[-1] == i:
                stack.pop()
            else:
                break
        else: 
            for j in range(stack_index+1, i):
                stack.append(j)
            stack_index = i
 
    return len(stack) == 0

if __name__ == '__main__':
    print(solution(2, [1, 2]) == 1)
    print(solution(3, [3, 1, 2]) == 0)
    print(solution(4, [1, 3, 2, 4]) == 1)

1 套碗游戏的取碗顺序问题(二)

问题描述

小F正在玩一个套碗的游戏,每个碗都有一个编号,从1到n,它们从大到小被套在一根木棍上。小F只能从木棍上取最上面的碗,每次只能取一个。现在你需要计算总共有多少种取碗的顺序。

例如,对于2个碗,取碗的顺序可以是 2 1 或 1 2,这两种顺序都是合法的。而对于3个碗,给定顺序 3 1 2 不可能通过合法操作实现,因此该顺序不可行。


测试样例

样例1:

输入:M = 2
输出:2

样例2:

输入:M = 3
输出:5

样例3:

输入:M = 4
输出:14

思路

这道题其实就是给定一个顺序的进栈顺序, 1-n,有多少种出栈顺序。 那就是卡特兰数的计算,可以用动态规划来解。

当一个无限大的栈中按照1到n的顺序进栈,合法的出栈序列数量即为第n个卡特兰数。 首次出空之前第一个出栈的序数k将1n的序列分成两个序列,其中一个是1k-1,序列个数为k-1,另外一个是k+1~n,序列个数是n-k。那么根据乘法定理,此时出栈的排列数就是(k-1) * (n-k) 而k的取值可以是1-n,所以给定n,答案就是k取1-n的累和。 这就是卡特兰数的一个递推式子: f(n)=f(0)f(n1)+...+f(n1)f(0)f(n) = f(0)*f(n-1) + ... + f(n-1)*f(0)

这是一个递推的过程,所以可以用动态规划数组来求解。

代码

def solution(M):
    dp = [0] * (M+1)
    dp[0] = 1
    for i in range(1,M+1):
        for j in range(1,i+1):
            dp[i] += dp[j-1]+ dp[i-j]

    # 或者
    # for i in range(1, M + 1):
    #     for j in range(i):
    #         dp[i] += dp[j] * dp[i - j - 1]

    return dp[M]

if __name__ == '__main__':
    print(solution(2) == 2)
    print(solution(3) == 5)
    print(solution(4) == 14)
    

其他问题

这类题目还可以在扩展,求出栈顺序的全排列。