给你一个 1 到 n 的排列和一个栈,并按照排列顺序入栈
你要在不打乱入栈顺序的情况下,仅利用入栈和出栈两种操作,输出字典序最大的出栈序列
排列:指 1 到 n 每个数字出现且仅出现一次
数据范围:
,排列中的值都满足
进阶:空间复杂度
,时间复杂度
[2,1,5,3,4]
[5,4,3,1,2]
操作 栈 结果 2 入栈;[2] [] 1 入栈;[2\1] [] 5 入栈;[2\1\5] [] 5 出栈;[2\1] [5] 3 入栈;[2\1\3] [5] 4 入栈;[2\1\3\4] [5] 4 出栈;[2\1\3] [5,4] 3 出栈;[2\1] [5,4,3] 1 出栈;[2] [5,4,3,1] 2 出栈;[] [5,4,3,1,2]
[1,2,3,4,5]
[5,4,3,2,1]
class Solution { public: /** * 栈排序 * @param a int整型一维数组 描述入栈顺序 * @param aLen int a数组长度 * @return int整型vector */ vector<int> solve(int* a, int aLen) { // write code here int j=0, n=aLen; vector<vector<int>> mr(n, vector<int>(2, 0)); int Max = INT_MIN; for(int i=n-1; i>=0; i--) { if(Max<a[i]) { Max = a[i]; j = i; } mr[i][0] = Max; mr[i][1] = j; } stack<int> st; vector<int> ans; for(int i=0; i<n; i++) { st.push(a[i]); if(i==mr[i][1]) { ans.push_back(st.top()); st.pop(); while(!st.empty() && i<n-1 && st.top()>mr[i+1][0]) { ans.push_back(st.top()); st.pop(); } } } while(!st.empty()) { ans.push_back(st.top()); st.pop(); } return ans; } };
public int[] solve (int[] a) { int n=a.length; Stack<Integer>stack=new Stack<>(); int[]dp=new int[n]; dp[n-1]=a[n-1]; for(int i=n-2;i>=0;i--) dp[i]=Math.max(dp[i+1],a[i]); //用一个数组记录第i个及之后最大元素 int[]res=new int[n]; int j=0; for(int i=0;i<n;i++){ stack.push(a[i]); while(!stack.isEmpty()&&i<n-1&&stack.peek()>=dp[i+1]) res[j++]=stack.pop();//如果栈顶元素比后面的都大,那么出栈 } while(!stack.isEmpty()) res[j++]=stack.pop(); //最后在栈中的按顺序弹出 return res; }
public int[] solve (int[] a) { // write code here int[] res = new int[a.length]; int pos = 0; Stack<Integer> indexStack = new Stack<>(); Stack<Integer> helperStack = new Stack<>(); // 构建单调栈,栈中存储元素下标,元素值单调递增 for (int i = 0; i < a.length; i++) { while (!indexStack.isEmpty() && a[indexStack.peek()] > a[i]) helperStack.push(indexStack.pop()); indexStack.push(i); while (!helperStack.isEmpty()) indexStack.push(helperStack.pop()); } // 开始未弹栈的全局最大值,通过单调栈可以直接获取 // 只有当当前值出现在最大值右侧时,才可以开始弹栈,否则最大值仍未出现,即使递减也不能立即弹栈 ArrayList<Integer> firstPopList = new ArrayList<>(); for (int i = 0; i < a.length; i++) { while (!indexStack.isEmpty() && indexStack.peek() <= i && a[indexStack.peek()] >= a[i]) { // 弹出到i的全局最大值,并继续寻找,直到循环退出 Integer pop = indexStack.pop(); firstPopList.add(pop); // 找出待弹出元素的真实索引顺序,同样只用栈实现 if (helperStack.isEmpty() || helperStack.peek() >= pop) helperStack.push(pop); else { // 使用 helperStack 排序,辅助栈 tmpStack Stack<Integer> tmpStack = new Stack<>(); while (helperStack.peek() < pop) tmpStack.push(helperStack.pop()); helperStack.push(pop); while (!tmpStack.isEmpty()) helperStack.push(tmpStack.pop()); } } // 将正确的顺序的元素填充到结果表 while (!helperStack.isEmpty())res[pos++] = a[helperStack.pop()]; } // 剩余的元素填充 if (!indexStack.isEmpty() && !firstPopList.isEmpty()) { for (int i = a.length - 1; i >= 0; i--) if (!firstPopList.contains(i)) res[pos++] = a[i]; } return res; }
public int[] solve (int[] a) { int len = a.length, pos = 0; Stack<Integer>stack = new Stack<>(); int[] res = new int[a.length]; int[]dp = new int[len]; dp[len - 1] = a[len - 1]; // 构建dp 数组,记录当前元素往后的最大值 for (int i = len - 2; i >= 0; i--) dp[i] = Math.max(dp[i + 1], a[i]); // 开始处理 push 时优先要弹出的元素 for (int i = 0; i < len; i++) { // 如果栈顶元素比当前元素的往后的最大值大,说明截止上个元素的的最大值已经出现,满足弹出条件,弹出到比当前元素小即可 if (!stack.isEmpty() && stack.peek() > dp[i] ) while (!stack.isEmpty() && stack.peek() >= dp[i]) res[pos++] = stack.pop(); stack.push(a[i]); } // 剩余的元素直接弹出 while (!stack.isEmpty()) res[pos++] = stack.pop(); return res; }
import java.util.*; public class Solution { public int[] solve (int[] a) { int[] rMax = new int[a.length]; // 当前位置之后的最大值(包括当前位置) rMax[a.length - 1] = a[a.length - 1]; for (int i = a.length - 2; i >= 0 ; i--) { rMax[i] = Math.max(rMax[i + 1], a[i]); } int index = 0; int[] res = new int[a.length]; Deque<Integer> stack = new ArrayDeque<>(); for (int i = 0; i < a.length; i++) { while (!stack.isEmpty() && stack.peek() > rMax[i]) { // 若栈顶比右侧大,则弹出 res[index++] = stack.pop(); } stack.push(a[i]); } while (!stack.isEmpty()) { res[index++] = stack.pop(); } return res; } }
class Solution { public: /** * 栈排序 * @param a int整型一维数组 描述入栈顺序 * @param aLen int a数组长度 * @return int整型vector */ vector<int> solve(int* a, int aLen) { // write code here stack<int> s; vector<int> res; vector<bool> f(aLen + 1, false); int now = aLen; for(int i = 0; i < aLen; i ++){ s.push(a[i]); f[a[i]] = true; while(now > 0 && f[now])now --; while(!s.empty() && s.top() > now){ res.push_back(s.top()); s.pop(); } } return res; } };
import java.util.*; /** * NC115 栈和排序 * @author d3y1 */ public class Solution { /** * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可 * * 栈排序 * @param a int整型一维数组 描述入栈顺序 * @return int整型一维数组 */ public int[] solve (int[] a) { // return solution1(a); // return solution2(a); return solution3(a); } /** * 模拟法: Stack+TreeSet * @param a * @return */ private int[] solution1(int[] a){ int n = a.length; TreeSet<Integer> treeSet = new TreeSet<>((o1, o2) -> (o2-o1)); for(int i=n-1; i>=0; i--){ treeSet.add(a[i]); if(a[i] == n){ break; } } int max = treeSet.pollFirst(); int[] result = new int[n]; Stack<Integer> stack = new Stack<>(); int i = 0; for(int num: a){ stack.push(num); treeSet.remove(num); if(stack.peek() == max){ result[i++] = stack.pop(); while(!stack.isEmpty() && !treeSet.isEmpty() && stack.peek()>treeSet.first()){ result[i++] = stack.pop(); } if(!treeSet.isEmpty()){ max = treeSet.pollFirst(); } } } while(!stack.isEmpty()){ result[i++] = stack.pop(); } return result; } /** * 模拟法: Stack(简化) * @param a * @return */ private int[] solution2(int[] a){ int n = a.length; // rMax[i]: i右侧最大值(不包括自身) int[] rMax = new int[n]; int max = a[n-1]; for(int i=n-2; i>=0; i--){ max = Math.max(max, a[i+1]); rMax[i] = max; } int[] result = new int[n]; Stack<Integer> stack = new Stack<>(); for(int i=0,j=0; i<n; i++){ stack.push(a[i]); if(stack.peek() == max){ result[j++] = stack.pop(); // rMax[n-1]=0 全部弹出 while(!stack.isEmpty() && stack.peek()>rMax[i]){ result[j++] = stack.pop(); } max = rMax[i]; } } return result; } /** * 模拟法: Stack(再简化) * @param a * @return */ private int[] solution3(int[] a){ int n = a.length; // rMax[i]: i右侧最大值(包括自身) int[] rMax = new int[n]; rMax[n-1] = a[n-1]; for(int i=n-2; i>=0; i--){ rMax[i] = Math.max(rMax[i+1], a[i]); } int[] result = new int[n]; Stack<Integer> stack = new Stack<>(); int j = 0; for(int i=0; i<n; i++){ while(!stack.isEmpty() && stack.peek()>rMax[i]){ result[j++] = stack.pop(); } stack.push(a[i]); } while(!stack.isEmpty()){ result[j++] = stack.pop(); } return result; } }
class Solution: def solve(self , a: List[int]) -> List[int]: stack = [] n = len(a) max_val = n res = [] for i in range(n): stack.append(a[i]) while stack and stack[-1] == max_val and i != n-1: res.append(stack.pop()) after_max = max(a[i+1:]) if stack and stack[-1] > after_max: max_val = stack[-1] else: max_val = after_max while stack: res.append(stack.pop()) return res
from operator import index # # 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可 # # 栈排序 # @param a int整型一维数组 描述入栈顺序 # @return int整型一维数组 # class Solution: def solve(self , a: List[int]) -> List[int]: # write code here if len(a) == 0&nbs***bsp;len(a) == 1: return a stack = [] stack.append(a[0]) res = [] # 构建右视图最大表 right_max = [0 for i in range(len(a))] right_max[-1] = a[-1] for i in range(len(a)-2, -1, -1): right_max[i] = max(a[i], right_max[i + 1]) index = 1 while index < len(a): if len(stack) == 0: stack.append(a[index]) index += 1 continue # 栈顶大于入栈数,将栈顶加入结果 if stack[-1] >= right_max[index]: res.append(stack[-1]) stack.pop() else: stack.append(a[index]) index += 1 while len(stack) != 0: res.append(stack[-1]) stack.pop() return res
import java.util.*; public class Solution { /** * 栈排序 * @param a int整型一维数组 描述入栈顺序 * @return int整型一维数组 */ public int[] solve (int[] a) { // write code here //保存要返回的值 int arr[]=new int[a.length]; //创建集合保存结果 ArrayList<Integer> list = new ArrayList<>(); //创建栈 Stack<Integer> stack = new Stack<>(); stack.push(a[0]); for (int i = 1; i < a.length; i++) { int max = max(a, i); //栈顶元素小于后面最大值,就入栈 if (stack.peek() < max) { stack.push(a[i]); } else { //栈顶元素大于后面最大值,说明已经找到最大的,就出栈 //循环遍历,直到栈顶比后面最大值还小 while(!stack.isEmpty()&&stack.peek()>max){ list.add(stack.pop()); } stack.push(a[i]); } } //将值添加到数组并返回 while(!stack.isEmpty()){ list.add(stack.pop()); } for(int i=0;i<list.size();i++){ arr[i]=list.get(i); } return arr; } public int max(int [] arr, int index) { int max = Integer.MIN_VALUE; for (int i = index; i < arr.length; i++) { if (arr[i] > max) { max = arr[i]; } } return max; } }
import java.util.*; public class Solution { /** * 栈排序 * @param a int整型一维数组 描述入栈顺序 * @return int整型一维数组 */ public int[] solve (int[] a) { // write code here int n = a.length; Deque<Integer> stack = new ArrayDeque<>(); int[] maxArr = new int[n]; // 倒叙记录每个位置元素后面出现的最大元素 maxArr[n-1] = Integer.MIN_VALUE; int tempMax = Integer.MIN_VALUE; for(int i=a.length-2;i>=0;i--){ maxArr[i] = Math.max(a[i+1], maxArr[i+1]); } for(int i=0;i<n;i++){ System.out.print(maxArr[i]+" "); } int[] ans = new int[n]; int index = 0; for(int i=0;i<n;i++){ if(a[i] > maxArr[i]){ // 当前入栈元素大于将要入栈的元素 ans[index++] = a[i]; while(!stack.isEmpty() && stack.peek()>maxArr[i]){ ans[index++] = stack.pop(); } }else{ stack.push(a[i]); } } while(!stack.isEmpty()){ ans[index++] = stack.pop(); } return ans; } }
# # 栈排序 # @param a int整型一维数组 描述入栈顺序 # @return int整型一维数组 # class Solution: def solve(self , a ): # write code here n, stack, dp, res = len(a), [], [0]*len(a), [] dp[-1] = a[-1] # 记录从第i个元素开始到最后的最大元素 for i in range(n-2, -1, -1): dp[i] = max(dp[i+1], a[i]) for i in range(n): stack.append(a[i]) while stack and i < n-1 and stack[-1]>=dp[i+1]: res.append(stack.pop()) # 如果栈顶元素比后面所有元素都大,则弹出 while stack: res.append(stack.pop()) return res
class Solution { public: /** * 栈排序 * @param a int整型一维数组 描述入栈顺序 * @param aLen int a数组长度 * @return int整型vector */ vector<int> solve(int* a, int aLen) { // write code here vector<int> res; stack<int> aux; int i=0; aux.push(a[i++]); while (aux.size()||i<=aLen){ if(i==aLen){ while(aux.size()){ res.push_back(aux.top()); aux.pop(); } i++; } else{ if(aux.size()){ int top=aux.top(); int next_max=*(std::max_element(a+i,a+aLen)); while(top>next_max){ aux.pop(); res.push_back(top); if(aux.size()) top=aux.top(); else break; } } aux.push(a[i++]); } } return res; } };