青训营X豆包MarsCode 技术训练营:AI刷题笔记-04 | 豆包MarsCode AI 刷题

109 阅读3分钟

AI的刷题笔记04

题目描述:套碗游戏的取碗顺序问题

小F正在玩一个套碗的游戏,每个碗都有一个编号,从1到n,它们从大到小被套在一根木棍上。小F只能从木棍上取最上面的碗,每次只能取一个。现在你需要判断给定的取碗顺序是否可行。如果可行,那么返回1,否则返回0. 例如,对于2个碗,取碗的顺序可以是2、1或1、2,这两种顺序都是合法的。而对于3个碗,给定顺序3、1、2不可能通过合法操作实现,因此该顺序不可行。

样例1

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

解题核心思路

将其模拟为一个栈的操作问题。我们可以使用栈来模拟从木棍上取碗的操作,检查给定的顺序是否可行。

题目分析

  • 小F有一根木棍,木棍上套着 M 个碗,编号从 1M。这些碗按照编号从小到大依次套在木棍上,比如编号 1 的碗最外面,编号 M 的碗最里面。
  • 他想按照一个给定的顺序 a 把碗取下来。每次只能从木棍的最外层(栈顶)取碗。
  • 如果顺序 a 不可能通过合法的取碗操作实现,就返回 0;如果可以,则返回 1

解题步骤

模拟取碗的过程,加入一个的概念。这个栈用来表示木棍上目前剩下的碗。栈的规则是 后进先出,也就是说,最上面的碗(栈顶)必须先取。符合题目所讲述的要求

准备阶段:定义
  • 一个栈 stack 用来模拟木棍上当前剩余的碗。
  • 一个变量 current 表示下一个将要放到木棍上的碗编号,初始值是 1,因为碗是从 1 开始放的。
模拟阶段:判断
  • 遍历给定的顺序 a,逐个看要取的碗编号。
  • 如果当前栈的最上面不是需要的碗,就从编号为 current 的碗开始,把碗依次放到木棍(栈)上,直到找到需要的碗。
  • 如果找到需要的碗,就从栈顶取出来。
  • 如果放到最后都找不到需要的碗,说明顺序不可能,返回 0
结束阶段:结果
  • 如果整个顺序都满足条件,所有碗都被成功取走,返回 1

最终代码

def solution(M, a):
    stack = []  # 用于模拟木棍上的碗
    current = 1  # 当前应该放到木棍上的碗编号
    
    for num in a:
        # 将需要的碗逐个放到栈中,直到栈顶是当前需要的碗
        while current <= M and (not stack or stack[-1] != num):
            stack.append(current)
            current += 1
        
        # 如果栈顶不是当前需要的碗,则顺序不可能
        if not stack or stack[-1] != num:
            return 0
        
        # 否则从栈顶取出碗
        stack.pop()
    
    # 如果所有碗都按顺序取完,返回 1
    return 1

代码解释

样例1:M=2,a=[1,2]

  1. 初始栈为空,current = 1
  2. 取第一个碗:
    • stack = [],将 1 放入栈中,stack = [1]
    • 栈顶是 1,取出 1stack = []
  3. 取第二个碗:
    • stack = [],将 2 放入栈中,stack = [2]
    • 栈顶是 2,取出 2stack = []
  4. 所有碗按顺序取完,返回 1

样例2:M=3,a=[3,1,2]

  1. stack 一开始是空的,current = 1
  2. 现在栈顶没有任何碗,所以从 current = 1 开始,把碗 1 放到栈里,栈变成 [1]
    • 再放碗 2,栈变成 [1, 2]
    • 再放碗 3,栈变成 [1, 2, 3]
  3. 栈顶是碗 3,正好是需要的,把它从栈里取走,栈变成 [1, 2]
  4. 现在栈顶是碗 2,但我们需要的是碗 1。这里就出问题了!
  5. 因为碗 1 被压在碗 2 的下面,我们没办法跳过碗 2 直接取碗 1,所以这时候顺序就不合法了。
  6. 返回 0,说明这组顺序不可行。