题目描述
输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如,序列 {1,2,3,4,5} 是某栈的压栈序列,序列 {4,5,3,2,1} 是该压栈序列对应的一个弹出序列,但 {4,3,5,1,2} 就不可能是该压栈序列的弹出序列。
示例1
输入:pushed = [1,2,3,4,5], popped = [4,5,3,2,1]
输出:true
解释:我们可以按以下顺序执行:
push(1), push(2), push(3), push(4), pop() -> 4,
push(5), pop() -> 5, pop() -> 3, pop() -> 2, pop() -> 1
示例2
输入:pushed = [1,2,3,4,5], popped = [4,3,5,1,2]
输出:false
解释:1 不能在 2 之前弹出。
算法分析
-
使用一个栈来执行出入栈操作,开始时持续将pushed中元素入栈,直到最新入栈元素等于popped中第 i(i == 0)个元素,此时开始执行出栈,每次出栈后将 i 加 1,直到栈顶元素不等于popped中第 i 个元素后才再次执行入栈操作。重复以上出入栈操作,最后根据popped中元素是否遍历完(即 i 是否等于 len(popped))判断popped是否为合法的出栈顺序。
-
该算法需要将所有元素出入栈一遍,因此需要花费 2 n 2n 2n的时间,即时间复杂度为O( 2 n 2n 2n) = O( n n n)。因为需要维护一个额外的栈,因此空间复杂度为O( n n n)。
Golang代码如下
type Stack struct {
val []interface{}
size int
}
func NewStack(v ...interface{}) *Stack {
s := &Stack{
v, len(v),
}
return s
}
func (s Stack) IsEmpty() bool {
return s.size == 0
}
func (s *Stack) Push(value interface{}) {
s.val = append((*s).val, value)
s.size++
}
func (s Stack) Top() interface{} {
if s.size == 0 {
return nil
}
return s.val[s.size - 1]
}
func (s *Stack) Pop() interface{} {
if s.size == 0 {
return nil
}
temp := s.val[s.size - 1]
s.val = s.val[:s.size - 1]
s.size--
return temp
}
func validateStackSequences(pushed []int, popped []int) bool {
if len(pushed) != len(popped) {
return false
}
s := NewStack()
i, j := 0, 0
for ; i < len(popped) && j < len(pushed); j++ {
if pushed[j] == popped[i] {
i++
for !s.IsEmpty() && s.Top() == popped[i] {
s.Pop()
i++
}
} else {
s.Push(pushed[j])
}
}
if i == len(popped) {
return true
}
return false
}