【剑指Offer】栈的压入、弹出序列——双指针实现

1.牛客网链接:我是链接

2.题目描述:
输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否可能为该栈的弹出顺序。假设压入栈的所有
数字均不相等。例如序列1,2,3,4,5是某栈的压入顺序,序列4,5,3,2,1是该压栈序列对应的一个弹出序列,但4,3,5,1,2就
不可能是该压栈序列的弹出序列。(注意:这两个序列的长度是相等的)
输入:栈的压入序列和弹出序列,例如压入序列{1,2,3,4,5},弹出序列{4,5,3,2,1}
输出:栈的弹出序列能否与栈的压入序列匹配(栈的弹出操作能否根据栈的压入顺序完成),能返回true,否则返回
false

3.题目分析:
我认为这道题的关键为:判断根据栈的弹出序列得到的栈顶元素弹出栈时,当前的栈顶是否为该元素。
在牛客的题解中有这一种思路:
(1)根据实际的栈数据结构(例如stack< int >)来判断:循环压入入栈序列的元素,当当前序列元素与当前出栈序列
元素相等时则执行出栈操作,最后在入栈元素全部压入(即循环结束后)判断栈内是否为空,如果为空则说明出栈序
列与入栈序列相匹配,函数返回true;如果栈内不为空说明出栈序列与入栈序列不匹配,返回false。

(2)我认为也可以不使用实际的栈结构解决这个问题:

  • a. 在某个元素出栈之前,需要栈中压入该元素,所以指向入栈序列的指针 int u 和出栈序列的指针 int o 可以理解
    为:出栈序列指针 int o 指向了当前需要出栈的元素,入栈序列指针 int u 指向了栈的栈顶元素(入栈序列可以看成一
    个动态变化的栈,序列下标的增大可以看成是元素的入栈,下标的减小可以看成是元素的出栈),并且使用set< int >
    index结构记录已经出栈过的元素(因为入栈序列没有相同的元素,出栈序列也一样)。
  • b. 循环遍历出栈序列 popV:当 popV[o] == pushV[u] 时 index.insert(popV[o])记录该元素已经出栈,并且将u置
    于当前的栈顶(while(u>0&&index.count(pushV[u]))u–);如果u==0或者popV[o] != pushV[u] ,则通过入栈操作
    找到popV[o] (在pushV中通过循环找到popV[o]),找到的话与上面popV[o]==pushV[u]时进行一样的操作,如果没
    找到(即push[u]越界)则返回false,说明所有的出栈操作没有完成,入栈序列与出栈序列不匹配;在最外层循环结束
    后说明所有的出栈操作都顺利完成了,入栈序列和出栈序列匹配,函数返回true。

4. C++代码实现:
我实现的方法为上面第二种思路:

class Solution {
public:
	bool IsPopOrder(vector<int> pushV, vector<int> popV) {
		if(pushV.empty()||popV.empty())return false;
        int o=0;//在出栈序列中指向需要出栈的栈顶元素
        int u=0;//在入栈序列中指向当前栈顶元素
        set<int> index;//记录已经出栈过的数据
        int num=pushV.size();//需要出栈的个数
        //出栈之前需要先入栈,并且出栈的是栈顶元素
        for(o=0;o<num;o++)//按照出栈顺序遍历popV
        {
            if(pushV[u]==popV[o]){//如果出栈栈顶等于当前入栈的元素
                index.insert(popV[o]);//记录该元素已经出栈过,不能再进行出栈
                while(u>0&&index.count(pushV[u]))u--;//将当前栈顶指向未出栈的元素
            }
            else if(o==0||pushV[u]!=popV[o])//如果需要出栈的元素是第一个/需要出栈的元素不为栈顶元素
            {
                for(;u<num;u++)//将当前栈顶元素后移==入栈
                {
                    if(pushV[u]==popV[o]){//如果当前栈顶元素等于当前需要出栈的元素,接下来的操作与上面相同
                        index.insert(popV[o]);
                        while(u>0&&index.count(pushV[u]))u--;
                        break;
                    }
                }
                if(u==num)return false;//如果在所有元素都入栈后没有找到当前需要出栈的元素popV[o],则popV与pushV不匹配返回false
            }
        }
        return true;//循环结束需要出栈的元素全都完成了出栈操作,返回true
	}
};
发布了30 篇原创文章 · 获赞 4 · 访问量 2729

猜你喜欢

转载自blog.csdn.net/qq_43167575/article/details/105611393