问题描述
小F在观察火车驶入和驶出休息区的顺序时,注意到休息区的结构类似于栈,即遵循先进后出的规则。她记录了火车驶入和驶出的顺序,并希望验证这些顺序是否可能实际发生。火车在进入休息区后可以按顺序驶入或停留,然后根据休息区的规则依次驶出。你的任务是帮助小F验证所记录的火车驶入和驶出顺序是否能够被满足。
例如:如果火车的驶入顺序是 1 2 3,驶出顺序是 3 2 1,这是可能的;如果驶出顺序是 3 1 2,则是不可能的。
测试样例
样例1:
输入:
n = 3, a = [1, 2, 3], b = [1, 2, 3]
输出:True
样例2:
输入:
n = 3, a = [1, 2, 3], b = [3, 2, 1]
输出:True
样例3:
输入:
n = 3, a = [1, 2, 3], b = [3, 1, 2]
输出:False
分析
数据结构选择
- 栈(Stack) :用于模拟休息区的火车,遵循先进后出的规则。
算法步骤
-
初始化栈:创建一个空栈,用于模拟休息区。
-
遍历驶出顺序:对于每一个驶出顺序中的火车,检查是否可以从栈中弹出。
-
处理栈顶元素:
- 如果栈顶元素与当前驶出顺序的火车匹配,弹出栈顶元素。
- 如果栈顶元素不匹配,继续驶入火车直到匹配或驶入顺序结束。
-
驶入顺序的处理:
- 如果栈顶元素不匹配,继续驶入火车直到找到匹配的火车或驶入顺序结束。
- 如果驶入顺序结束且未找到匹配的火车,说明无法按驶出顺序驶出,返回
False。
-
最终判断:如果所有火车都能按驶出顺序驶出,返回
True,否则返回False。
难点分析
-
栈的操作:
- 需要正确理解栈的先进后出特性,并能够在代码中正确模拟栈的操作。
- 栈顶元素的检查和弹出操作需要与驶出顺序的火车匹配。
-
驶入顺序的处理:
- 当栈顶元素与驶出顺序的火车不匹配时,需要继续驶入火车,直到找到匹配的火车或驶入顺序结束。
- 如果驶入顺序结束且未找到匹配的火车,说明无法按驶出顺序驶出,这是一个关键的判断点。
-
边界条件:
- 需要处理驶入顺序和驶出顺序的边界条件,确保所有火车都能正确处理。
- 如果驶入顺序和驶出顺序的长度不一致,或者驶入顺序中没有对应的火车,需要正确处理这些情况。
贴代码(嗯!
def solution(n: int, a: list, b: list) -> bool:
# 初始化一个栈
stack = []
# 初始化驶入顺序的索引
i = 0
# 遍历驶出顺序
for out in b:
# 如果栈顶元素与当前驶出顺序的火车匹配
if stack and stack[-1] == out:
# 弹出栈顶元素
stack.pop()
else:
# 否则,继续驶入火车直到匹配或驶入顺序结束
while i < n and a[i] != out:
stack.append(a[i])
i += 1
# 如果驶入顺序结束且未找到匹配的火车
if i == n:
return False
# 找到匹配的火车,驶入并驶出
i += 1
# 如果所有火车都能按驶出顺序驶出,返回 True
return True
if __name__ == '__main__':
print(solution(3, [1, 2, 3], [1, 2, 3]) == True)
print(solution(3, [1, 2, 3], [3, 2, 1]) == True)
print(solution(3, [1, 2, 3], [3, 1, 2]) == False)
-
栈的操作:
- 栈的先进后出特性非常适合模拟火车的驶入和驶出过程。
- 栈的操作(入栈和出栈)是高效的,时间复杂度为 O(1)。
-
驶入顺序的处理:
- 通过遍历驶入顺序,我们可以将火车逐个驶入栈中。
- 当栈顶元素与驶出顺序的火车不匹配时,继续驶入火车直到找到匹配的火车或驶入顺序结束。
- 这个过程是线性的,时间复杂度为 O(n),其中 n 是火车的数量。
-
边界条件:
- 需要处理驶入顺序和驶出顺序的边界条件,确保所有火车都能正确处理。
- 如果驶入顺序和驶出顺序的长度不一致,或者驶入顺序中没有对应的火车,需要正确处理这些情况。