题目描述
输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否可能为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如序列1,2,3,4,5是某栈的压入顺序,序列4,5,3,2,1是该压栈序列对应的一个弹出序列,但4,3,5,1,2就不可能是该压栈序列的弹出序列。(注意:这两个序列的长度是相等的)
解题思路:
思路一:
题是想走栈的思想路线,那么就设计一个栈来进行,看出栈顺序能不能跟给出的出栈顺序相匹配。如果匹配则正确,否则错误。
具体做法:
设计两个标记来指向两个入栈和出栈序列,开始当然是入栈先走即往新建的栈中压进去,之后这个标记往后走一步。用压入的这个数据和出栈序列的标记数据比较,如果相同就把这个数据出栈,并且把出栈序列上的标记往后走一步。否则出栈序列标记就不走。接着再将入栈序列往里面压循环接着判断。终止就是最后循环终止时,如果压入栈的数据能和出栈序列匹配着全部出栈,则出栈序列正确。否则不正确。
代码:
bool IsPopOrder(vector<int> pushV, vector<int> popV) { stack<int> st; size_t pushIndex = 0, popIndex = 0; while (pushIndex < pushV.size()) { st.push(pushV[pushIndex++]); while (!st.empty() && st.top() == popV[popIndex]) { st.pop(); popIndex++; } } return st.empty(); }
思路二:
根据栈的特点,先入后出,后入先出的特点。那么这就意味着,当出栈一个数据时,在这个数据之前入栈的数据必将是倒着出栈。根据这一特性,只需判断它前面数据的下标大小关系是否反着的即可。
代码:
class Solution { public: bool IsPopOrder(vector<int> pushV,vector<int> popV) { if (pushV.size() != popV.size()) { return false; } int size = pushV.size(); for (int i = 0; i < size; i++) { int data = popV[i]; //找出pop数据在入栈的位置 int j = FindDataPos(pushV, data); if (j < 0) { return false; } //pop每个元素在push中前面的数据必须逆序,有一个不逆序就说明错误出栈 while (j - 1 > 0) { //记录入栈前两个元素在出栈中的位置 int PopBackLocat = FindDataPos(popV, pushV[j - 1]); //当个数相同而数据不一样时。就是数据对不上 if (PopBackLocat < 0) { return false; } int PopFrontLocat = FindDataPos(popV, pushV[j - 2]); if (PopFrontLocat < 0) { return false; } //只能在当前出栈的后面来判断 if (PopBackLocat > i && PopFrontLocat > i) { if (PopBackLocat > PopFrontLocat) { return false; } } j--; } } return true; } int FindDataPos(vector<int> v, int data) { size_t size = v.size(); for (size_t i = 0; i < size; i++) { if (data == v[i]) { return i; } } return -1; } };
运行结果:
注意:
在实现第二种时注意的细节比较多,表现在以下四点:
1.在开始入栈,出栈的个数相同后,在入栈序列中找出栈序列的第一个数据时,注意对找不到的情况进行判断。
2.在找寻出栈元素的前面数据时注意也要对找不到找得到进行判断。
3.我在这个上出错的原因是一开始将查找数据的返回值给成立size_t类型,这样导致对查找的结果无法进行判断导致错误,int,size_t注意慎用。
4.在判断出栈数据的前两个数据时注意它一定是出现在出栈元素位置的后面,如果出现在前面那么说明了什么???
那说明了,已经把前面这个元素已经先比较过了所以它是可以的。我会举个例子在后面的运行结果中。就像出栈时的2,3序列一样(例子在后面)
运行特殊出栈序列:
珍&源码