判断取碗顺序的合法性| 豆包MarsCode AI 刷题

100 阅读3分钟

一、题目描述

小F玩套碗游戏,每个碗编号从1到n,按从大到小的顺序套在木棍上。每次只能从最上面取一个碗。给定一个取碗顺序,判断是否可以通过合法操作实现。

例子:

  • 输入:M = 2, a = [1, 2],输出:1(合法)。
  • 输入:M = 3, a = [3, 1, 2],输出:0(不合法)。
  • 输入:M = 4, a = [1, 3, 2, 4],输出:1(合法)。

二、解题思路

这类问题可以通过(stack)来模拟木棍的操作逻辑。栈符合先进后出的特点,非常适合用来表示套碗的顺序。

核心逻辑:

  1. 每次只允许从栈顶取出碗。
  2. 如果当前要取的碗不在栈顶,就需要按编号顺序将碗依次压入栈中,直到目标碗到达栈顶。
  3. 如果目标碗不能到达栈顶,说明顺序不合法。

三、具体实现步骤

  1. 定义一个空栈 stack
  2. 设定变量 current = 1,表示下一个即将压入栈的碗编号。
  3. 遍历取碗顺序 a
    • 如果当前碗在栈顶,直接弹出。
    • 如果当前碗不在栈顶,则将 current 到目标碗之间的碗依次压入栈,直到目标碗在栈顶,再弹出。
    • 如果以上操作无法满足,返回0(非法操作)。
  4. 如果遍历完成,返回1(合法操作)。

四、代码实现

def solution(M: int, a: list) -> int:
    stack = []
    current = 1  # 表示即将压入栈的碗编号
    
    for num in a:
        # 压栈直到目标碗 num 出现在栈顶
        while current <= M and (not stack or stack[-1] != num):
            stack.append(current)
            current += 1
        
        # 如果目标碗在栈顶,则弹出
        if stack and stack[-1] == num:
            stack.pop()
        else:
            return 0  # 不合法,返回0
    
    return 1  # 全部合法,返回1

五、测试与验证

# 测试用例
print(solution(2, [1, 2]))  # 输出:1
print(solution(3, [3, 1, 2]))  # 输出:0
print(solution(4, [1, 3, 2, 4]))  # 输出:1

结果分析:

  1. 测试用例1:取碗顺序[1, 2]可以按顺序依次压入弹出,合法。
  2. 测试用例2:取碗顺序[3, 1, 2]中,碗1需要先于碗2被取出,但实际操作中无法实现,非法。
  3. 测试用例3:取碗顺序[1, 3, 2, 4]可以通过依次压入和弹出实现,合法。

六、时间复杂度分析

  • 压栈和弹栈操作:每个碗最多被压入和弹出一次,复杂度为 (O(M))。
  • 总复杂度:由于遍历了整个取碗顺序数组,总体时间复杂度为 (O(M))。

七、总结与收获

  1. 栈的使用:栈非常适合模拟这类“先进后出”的问题。
  2. 问题建模:通过分析规则,将问题抽象为栈的压入和弹出过程。
  3. 边界条件:注意在每一步都需要检查目标碗是否在栈顶,或者是否已经压入栈中。

这道题巩固了栈在模拟现实问题中的应用,类似问题还可以扩展到括号匹配、文件路径解析等领域。