要求:
输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否可能为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如序列1,2,3,4,5是某栈的压入顺序,序列4,5,3,2,1是该压栈序列对应的一个弹出序列,但4,3,5,1,2就不可能是该压栈序列的弹出序列。
1. 0<=pushV.length == popV.length <=1000
2. -1000<=pushV[i]<=1000
3. pushV 的所有数字均不相同
示例1:
输入:
[1,2,3,4,5],[4,5,3,2,1]返回值:
true说明:
可以通过push(1)=>push(2)=>push(3)=>push(4)=>pop()=>push(5)=>pop()=>pop()=>pop()=>pop() 这样的顺序得到[4,5,3,2,1]这个序列,返回true示例2:
输入:
[1,2,3,4,5],[4,3,5,1,2]返回值:
false说明:
由于是[1,2,3,4,5]的压入顺序,[4,3,5,1,2]的弹出顺序,要求4,3,5必须在1,2前压入,且1,2不能弹出,但是这样压入的顺序,1又不能在2之前弹出,所以无法形成的,返回false 。
思路:
方法一:辅助栈
首先创建一个辅助栈stack。遍历pushV,将压入栈pushV中的元素依次压入辅助栈stack中,比较辅助栈stack的栈顶元素与弹出栈popV的第一个元素是否相等,当两者相等时,停止将压入栈pushV中的元素依次压入辅助栈stack中,并弹出stack栈中的顶部元素。
接着继续往辅助栈stack中压入元素,同时继续比较辅助栈stack的栈顶元素与弹出栈popV的第二个元素是否相等,如果相等,停止压入操作,并弹出stack栈中的栈顶元素。
……
重复上述工作,直到辅助栈stack为空栈。此时popV的元素顺序就是压入栈pushV的弹出顺序。
图解:
比较辅助栈stack的栈顶元素与弹出栈popV的第一个元素是否相等,发现有元素相等时,就停止压入,同时弹出这个栈顶元素:
接着继续压入pushV中的元素,比较辅助栈stack的栈顶元素与弹出栈popV的第二个元素是否相等,当发现相等元素时:
重复上述操作,直到辅助栈stack为空,且弹出栈popV的元素顺序值与popV的长度相等。
代码实现:
def IsPopOrder(pushV, popV):
j = 0
stack = [] # 用列表初始化辅助栈stack
for x in pushV: # 把压入栈pushV中的元素依次压入辅助栈stack中
stack.append(x)
while stack and stack[-1] == popV[j]:
stack.pop()
j = j + 1
return j == len(popV)
pushV = [1, 2, 3, 4, 5]
popV = [4, 3, 5, 2, 1]
print(IsPopOrder(pushV, popV))
# True
方法二:直接在pushV上进行操作
- 当pushV[i] != popV[0]元素,表示还没匹配到待弹出元素;继续i = i + 1压入元素;
- 当push[i] == popV[0]时,即匹配到待弹出元素,并i = i - 1让它始终指向pushV的顶部元素(也就相当于是弹出了栈顶元素);同时popV也要更新到下一个元素j = j + 1,使其成为新的popV[0]。最后直到pushV 和popV都为空即匹配结束。
代码实现:
def IsPopOrder(self, pushV, popV):
i = j = 0
for x in pushV:
pushV[i] = x
while i >= 0 and pushV[i] == popV[j]: # 当pushV的当前元素等于popV弹出的顶部元素时中止循环
i, j = i - 1, j + 1 # 分别更新栈顶的元素
i += 1 # 否则继续往pushV中添加元素
return i == 0 # 直到pushV的索引减小到0
pushV = [1, 2, 3, 4, 5]
popV = [4,3,5,1,2]
print(IsPopOrder(pushV, popV))
# False