【剑指offer】33.栈的压入、弹出序列
总目录:
1.问题描述
输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否可能为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如序列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 的所有数字均不相同
2.问题分析
1压栈弹栈,检查不合理之处:当前弹出元素的下一个元素,如果既不是当前的栈顶(可弹出元素),也不是待压入元素,则错误
2压栈改良版,主要是浓缩压栈逻辑,要么压栈到和当前弹出的元素匹配,要么就压完为止
3原地栈,直接用数组索引来判断,暂时未看懂
3.代码实例
压栈弹栈
1 class Solution { 2 public: 3 stack<int> st; 4 int getItemIndex(vector<int>& vec, int val) { 5 int itemLength = vec.size(); 6 for (int i = 0; i < itemLength; i++) { 7 if (vec[i] == val) { 8 return i; 9 } 10 } 11 12 //不存在的元素 13 return -1; 14 } 15 16 bool IsPopOrder(vector<int> pushV, vector<int> popV) { 17 //二者长度是否一致 18 if (pushV.size() != popV.size()) { 19 return false; 20 } 21 22 int itemNum = pushV.size(); 23 int curPushIndex = -1; 24 int curItemRawIndex = 0; 25 26 //逐元素检查弹出数据是否合理 27 for (int i = 0; i < itemNum; i++) { 28 //获取当前弹出元素在原集合中的索引 29 curItemRawIndex = getItemIndex(pushV, popV[i]); 30 if (curItemRawIndex < 0) { 31 return false; 32 } 33 34 //如果已经检查至最后一个,则不必继续进行 35 if ((i + 1) >= itemNum) { 36 return true; 37 } 38 39 //将尚未压入内容全部压栈 40 if (curItemRawIndex > curPushIndex) { 41 for (int j = curPushIndex + 1; j <= curItemRawIndex; j++) { 42 st.push(pushV[j]); 43 } 44 45 //更新当前压入索引 46 curPushIndex = curItemRawIndex; 47 } 48 49 //因为当前元素已经进入了弹出队列 50 st.pop(); 51 52 //检查下一个弹出元素是否合理 53 //不合理情况:既不等于下一个可弹出元素,也不等于尚未压入元素 54 int nextItemRawIndex = getItemIndex(pushV, popV[i + 1]); 55 if (popV[i + 1] != st.top() && 56 nextItemRawIndex <= curPushIndex) { 57 return false; 58 } 59 } 60 61 return true; 62 } 63 };
压栈改良版
1 class Solution { 2 public: 3 bool IsPopOrder(vector<int> pushV,vector<int> popV) { 4 int n = pushV.size(); 5 //辅助栈 6 stack<int> s; 7 //遍历入栈的下标 8 int j = 0; 9 //遍历出栈的数组 10 for(int i = 0; i < n; i++){ 11 //入栈:栈为空或者栈顶不等于出栈数组 12 while(j < n && (s.empty() || s.top() != popV[i])){ 13 s.push(pushV[j]); 14 j++; 15 } 16 //栈顶等于出栈数组 17 if(s.top() == popV[i]) 18 s.pop(); 19 //不匹配序列 20 else 21 return false; 22 } 23 return true; 24 } 25 };
原地栈
1 class Solution { 2 public: 3 bool IsPopOrder(vector<int> pushV,vector<int> popV) { 4 //表示栈空间的大小,初始化为0 5 int n = 0; 6 //出栈序列的下标 7 int j = 0; 8 //对于每个待入栈的元素 9 for(int num : pushV){ 10 //加入栈顶 11 pushV[n] = num; 12 //当栈不为空且栈顶等于当前出栈序列 13 while(n >= 0 && pushV[n] == popV[j]){ 14 //出栈,缩小栈空间 15 j++; 16 n--; 17 } 18 n++; 19 } 20 //最后的栈是否为空 21 return n == 0; 22 } 23 };