输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如,序列{1, 2, 3, 4, 5}是某栈的压栈序列,序列{4, 5, 3, 2, 1}是该栈序列对应的一个弹出序列,但{4, 3, 5, 1, 2}就不可能是该压栈序列的弹出序列。
提示: 这两个序列的长度是相等的。
示例:
输入:pushed = [1, 2, 3, 4, 5],poped = [4, 5, 3, 2, 1]
输出:true
思路:
对于该题目,我们可以使用一个栈来模拟进行第一个序列的入栈和出栈操作,如果可以模拟出第二个序列,则第二个序列是以第一个序列为压栈顺序的某一弹出序列。
首先用两个变量 i 和 j ,分别索引当前正在遍历的两个序列的元素位置。然后开始循环执行以下过程,直到第一个序列被遍历完毕为止:
- 先将第一个序列当中 i 索引的元素压栈,然后 i 转而索引第一个序列的后一个元素。
- 判断栈顶元素与第二个序列当中 j 索引的元素是否相同,若相同则将栈顶的元素弹出,然后 j 转而索引第二个序列的后一个元素,并继续当前判断,直到栈顶元素与 j 索引的元素不同或是栈已经为空为止。
当该过程执行完毕后,若第二个序列已经遍历完毕或者说栈已经为空(选一个作为最终判断即可),则第二个序列是以第一个序列为压栈顺序的某一弹出序列。
下面我们以就以上面给出的示例为列,具体说明一下:
首先,初始状态下,让 i 和 j 分别指向第一个序列和第二个序列的第一个元素。
然后让 i 索引的元素入栈,并让 i 转而索引后一个元素。
接着判断栈顶元素与 j 索引的元素是否相同,此时不同,则继续将 i 索引的元素入栈,并让 i 转而索引后一个元素。
然后再判断栈顶元素与 j 索引的元素是否相同,此时还是不同,则继续将 i 索引的元素入栈,并让 i 转而索引后一个元素。
紧接着再判断栈顶元素与 j 索引的元素是否相同,此时还是不同,则继续将 i 索引的元素入栈,并让 i 转而索引后一个元素。
这时我们发现栈顶元素与 j 索引的元素相同,则将栈顶的元素弹出,并让 j 转而索引后一个元素。
然后我们又判断栈顶元素与 j 索引的元素是否相同,此时不同,则继续将 i 索引的元素入栈,并让 i 转而索引后一个元素。
这时我们再次发现栈顶元素与 j 索引的元素相同,则将栈顶的元素弹出,并让 j 转而索引后一个元素。
此时发现栈顶元素与 j 索引的元素还是相同的,则将栈顶的元素继续弹出,并让 j 转而索引后一个元素。
栈顶元素与 j 索引的元素还是相同的,则将栈顶的元素继续弹出,并让 j 转而索引后一个元素。
栈顶元素与 j 索引的元素还是相同的,则将栈顶的元素继续弹出,并让 j 转而索引后一个元素。
好了现在栈空了,不能再判断栈顶的元素与 j 索引的元素是否相同了,现在本该继续将 i 索引的元素入栈,但现在 i 已经指向第一个序列末尾,于是操作结束。现在我们发现第二个序列也已经遍历完毕或者说栈现在已经为空,于是得出结论:第二个序列{4, 5, 3, 2, 1}是以第一个序列{1, 2, 3, 4, 5}为压栈顺序的某一弹出序列。
代码如下:
class Solution {
public:
bool validateStackSequences(vector<int>& pushed, vector<int>& popped) {
size_t i = 0, j = 0; //分别索引当前正在遍历的两个序列的元素位置
stack<int> st; //辅助栈
while (i < pushed.size()) //反复执行该操作,直到第一个序列被遍历完毕
{
st.push(pushed[i]); //将第一个序列当中i索引的元素压栈
while (!st.empty() && st.top() == popped[j]) //判断栈顶元素与第二个序列当中j索引的元素是否相同,直到栈顶元素与j索引的元素不同或是栈已经为空为止
{
st.pop(); //若相同则将栈顶的元素弹出
j++; //j转而索引第二个序列的后一个元素,并继续当前判断
}
i++; //索引pushed容器中的下一个元素
}
//return j == popped.size(); //判断第二个序列是否遍历完毕,若是,则匹配
return st.empty(); //判断辅助栈是否为空,为空则匹配
}
};