首页 > 试题广场 >

用一个栈实现另一个栈的排序

[编程题]用一个栈实现另一个栈的排序
  • 热度指数:6296 时间限制:C/C++ 5秒,其他语言10秒 空间限制:C/C++ 256M,其他语言512M
  • 算法知识视频讲解
一个栈中元素的类型为整型,现在想将该栈从顶到底按从大到小的顺序排序,只许申请一个栈。除此之外,可以申请新的变量,但不能申请额外的数据结构。如何完成排序?

输入描述:
第一行输入一个N,表示栈中元素的个数
第二行输入N个整数a_i表示栈顶到栈底的各个元素


输出描述:
输出一行表示排序后的栈中栈顶到栈底的各个元素。
示例1

输入

5
5 8 4 3 6

输出

8 6 5 4 3

备注:
1 <= N <= 10000
-1000000 <= a_n <= 1000000
看到不少朋友说有问题,我下面的代码是完美通过,如果通过率是95.24%,可以看看我注释的部分。
事实上这道题数据是会影响效率的,最快的时间复杂度为O(N),最差则是O(N^2);题目中说了:第二行输入N个整数a_iai表示栈顶到栈底的各个元素
如果你获取输入直接push到栈中,那么你的顺序是栈底到栈顶,是不符合题目要求的。
import java.util.*;

public class Main{
    
   public static void sortStack(Stack<Integer> stack) {
        Stack<Integer> help = new Stack<>();
        while (!stack.isEmpty()) {
            int cur = stack.pop();
            while (!help.isEmpty() && cur > help.peek()) {
                stack.push(help.pop());
            }
            help.push(cur);
        }
        while (!help.isEmpty()) {
            stack.push(help.pop());
        }
    }

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int n = scanner.nextInt();
        int[] arr = new int[n];
        for (int i = n - 1; i >= 0; i--) {
           arr[i] = scanner.nextInt();
        }
        // for (int i = 0; i < n; i++) { // 错误示范: case通过率为95.24%
        //    arr[i] = scanner.nextInt();
        // }
        Stack<Integer> stack = new Stack();
        for (int item : arr) {
            stack.push(item);
        }
        sortStack(stack);
        while (!stack.isEmpty()) {
            System.out.print(stack.pop() + " ");
        }
    }
}


发表于 2020-02-29 11:43:55 回复(2)
python3代码:
彻底无语了,通过率71.43%,说我算法复杂度大,这是标准写法啊拜托
import sys

class OrderHelpStack(object):
    def orderStack(self, stack):
        helpStack = []
        while stack:
            stackTop = stack.pop()
            while helpStack and stackTop > helpStack[-1]:
                stack.append(helpStack.pop())
            helpStack.append(stackTop)
        while helpStack:
            stack.append(helpStack.pop())
        return stack


N = int(sys.stdin.readline().strip())
stack = []
orderHelpStack = OrderHelpStack()
line = sys.stdin.readline().strip()
words = line.split()
for word in words:
    stack.append(int(word))
stack = orderHelpStack.orderStack(stack)
result = ""
for i in range(N-1):
    result += str(stack.pop()) + " "
result += str(stack.pop())
print(result)


发表于 2019-08-17 20:32:36 回复(9)
#include<bits/stdc++.h>
using namespace std;
int main()
{
    int i;
    int n,x;
    stack<int> s,help;
    cin>>n;
    vector<int> arr(n,0);
    for(i=0;i<n;i++)
    {
        cin>>x;
        arr.at(i)=x;
    }
    for(i=n-1;i>=0;i--)
        s.push(arr.at(i));
    while(!s.empty())
    {
        int temp=s.top();
        s.pop();
        while(!help.empty()&&help.top()>temp)
        //这里一开始第二条件使用help.top()>=temp,结果
        //超时严重,应该是测试数据有极端测试数据,导致程序
        //交换过多导致的
        {
            s.push(help.top());
            help.pop();
        }
        help.push(temp);
    }
    while(!help.empty())
    {
        if(help.size()==1) cout<<help.top();
        else cout<<help.top()<<" ";
        help.pop();
    }
    return 0;
}

发表于 2020-05-11 16:33:31 回复(0)
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Deque;
import java.util.LinkedList;

public class Main {
    static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    public static void main(String[] args) throws IOException {
        br.readLine();
        String[] secondLine = br.readLine().split(" ");
        Deque<Integer> stack = new LinkedList<>();
        Deque<Integer> help = new LinkedList<>();
        for (String s : secondLine) {
            stack.push(Integer.parseInt(s));
        }
        while (!stack.isEmpty()) {
            int cur = stack.pop();
            while (!help.isEmpty() && cur > help.peek()) {
                stack.push(help.pop());
            }
            help.push(cur);
        }
        while (!help.isEmpty()) {
            stack.push(help.pop());
        }
        StringBuilder res = new StringBuilder();
        while (!stack.isEmpty()) {
            res.append(stack.pop());
            if (!stack.isEmpty()) {
                res.append(" ");
            }
        }
        System.out.println(res);
    }
}

发表于 2022-02-18 23:53:08 回复(0)
思路很简单,用题目给的例子进行说明:
stack1: [5 8 4 3 6] -> [5 8 4 3] -> [5 8 4 6] -> [5 8 4] -> [5 8 6] -> [5 8]    -> [5]          -> [8 6]    -> []
stack2: []               -> [6]          -> [3]          -> [3 6]    -> [3 4]    -> [3 4 6] -> [3 4 6 8] -> [3 4 5] -> [3 4 5 6 8]
整体思路就是每次stack1弹出的元素val与stack2的栈顶元素比较大小,如果大就直接压栈,否则将stack2的元素弹出并压回stack1,直到栈顶元素小于val,再把val压入stack2,从而一直保证stack2的单调性。
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;
import java.util.Stack;

public class Main {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        Stack<Integer> stack1 = new Stack<>(), stack2 = new Stack<>();
        int n = Integer.parseInt(br.readLine());
        String[] strArr = br.readLine().split(" ");
        for(int i = 0; i < n; i++)
            stack1.push(Integer.parseInt(strArr[i]));
        while(!stack1.isEmpty()){
            int peekVal = stack1.pop();
            if(stack2.isEmpty()){
                stack2.push(peekVal);
            }else{
                if(peekVal >= stack2.peek()){
                    stack2.push(peekVal);
                }else{
                    while(!stack2.isEmpty() && peekVal < stack2.peek())
                        stack1.push(stack2.pop());
                    stack2.push(peekVal);
                }
            }
        }
        while(!stack2.isEmpty())
            System.out.print(stack2.pop() + " ");
    }
}

编辑于 2021-06-15 12:19:39 回复(0)
import java.util.Scanner;
import java.util.Stack;

public class Main {

    public static void sortStackByStack(Stack<Integer> stack) {
        Stack<Integer> help = new Stack<>();
        while (!stack.isEmpty()) {
            int temp = stack.pop();
            while (!help.isEmpty() && help.peek() > temp) {
                stack.push(help.pop());
            }
            help.push(temp);
        }
        while (!help.isEmpty()) {
            int temp = help.pop();
            stack.push(temp);
            System.out.print(temp + " ");
        }
    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        Stack<Integer> stack = new Stack<>();
        while (n-- > 0) {
            stack.push(sc.nextInt());
        }
        sortStackByStack(stack);
    }

}
发表于 2019-10-10 18:32:47 回复(0)
看到自己6300+ms然后看到你们160+ms,开始怀疑人生;
点进去看了下你们竟然偷偷用库函数.....
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Stack;

public class Main {

    public static void sortStackByStack(Stack<Integer> stack) {
        Stack<Integer> help = new Stack<>();
        while (!stack.isEmpty()) {
            int cur = stack.pop();
            while (!help.isEmpty() && help.peek() < cur) {
                stack.push(help.pop());
            }
            help.push(cur);
        }
        while (!help.isEmpty()) {
            stack.push(help.pop());
        }
    }

    public static void main(String[] args) throws IOException {
        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
        Stack<Integer> helpInput = new Stack<>();
        int n = Integer.parseInt(in.readLine());
        String[] stackArray = in.readLine().split(" ");
        for (int i = n-1;i >=0;i--){
            helpInput.push(Integer.parseInt(stackArray[i]));
        }
        sortStackByStack(helpInput);
        while (!helpInput.isEmpty()){
            System.out.print(helpInput.pop()+ " ");
        }
        in.close();
    }
}

发表于 2020-04-04 21:28:21 回复(0)
#include<bits/stdc++.h>
using namespace std;
int main()
{
    int n;
    cin>>n;
    vector<int>num(n);
    for(int i=0;i<n;i++)
        cin>>num[i];
    sort(num.begin(),num.end(),greater<int>());
    for(int i=0;i<n;i++)
        cout<<num[i]<<" ";
    return 0;
}

发表于 2019-08-24 22:46:18 回复(0)
#include <bits/stdc++.h>
using namespace std;

int main(){
    stack<int> S1, S2;
    int n, x, t;
    cin>>n;
    for(int i=0;i<n;i++){
        cin>>x;
        S1.push(x);
    }
    while(!S1.empty()){
        x = S1.top();
        S1.pop();
        if(S2.empty())
            S2.push(x);
        else{
            t = S2.top();
            while(!S2.empty() && t>x){
                S2.pop();
                S1.push(t);
                t = S2.top();
            }
            S2.push(x);
        }
    }
    while(!S2.empty()){
        cout<<S2.top()<<" ";
        S2.pop();
    }
    return 0;
}

编辑于 2020-02-07 11:27:36 回复(3)
放一个golang的版本
package main

import (
	"fmt"
)

func main() {
	num := 0
	fmt.Scan(&num)

	s := Stack{}

	for i := 0; i < num; i++ {
		v := 0
		fmt.Scan(&v)
		s.Push(v)
	}

	sortStack(&s)

	for !s.IsEmpty() {
		fmt.Print(s.Pop())
		fmt.Print(" ")
	}

	fmt.Println("")
}

func sortStack(s *Stack) {
	t := Stack{}

	for !s.IsEmpty() {
		top := s.Pop()

		for !t.IsEmpty() && top > t.Top() {
			s.Push(t.Pop())
		}

		t.Push(top)
	}

	for !t.IsEmpty() {
		s.Push(t.Pop())
	}
}

type Stack struct {
	data []int
}

func (s *Stack) Push(v int) {
	s.data = append(s.data, v)
}

func (s *Stack) Pop() int {
	top := s.data[len(s.data)-1]
	s.data = s.data[:len(s.data)-1]
	return top
}

func (s *Stack) IsEmpty() bool {
	return len(s.data) == 0
}

func (s *Stack) Top() int {
	return s.data[len(s.data)-1]
}

发表于 2023-08-23 17:20:02 回复(0)
python解法超时了
import sys

# 处理输入
N = sys.stdin.readline().strip()
stack = [int(i) for i in sys.stdin.readline().strip().split()]


# 使用辅助栈,基于汉诺塔原理实现栈的排序
def sortStack(stack):
    helper = []
    while stack:
        val = stack.pop()
        if not helper:
            helper.append(val)
        else:
            while helper and val > helper[-1]:
                stack.append(helper.pop())
            helper.append(val)
    while helper:
        stack.append(helper.pop())
    return stack

stack = sortStack(stack)
while stack:
    print(stack.pop(), end=' ')


发表于 2022-06-01 16:22:27 回复(0)
按题意只能用一个栈,但是不用两个栈怎么保存pop出来的元素?
#include <bits/stdc++.h>

using namespace std;

stack<int> stOut;     // 输出栈
void push(stack<int>& stIn)
{
    while(!stIn.empty()){
        int tmp = stIn.top();
        stIn.pop();
        // 输出栈顶元素比当前元素大,就不断 pop 出来,重新插入输入栈
        while(!stOut.empty() && tmp < stOut.top()){
            int top = stOut.top();
            stOut.pop();
            stIn.push(top);
        }
        // 否则就插入输出栈
        stOut.push(tmp);
    }
}
int main()
{
    int n;
    cin >> n;
    vector<int> nums(n);
    for(int i = 0; i < n; ++i) cin >> nums[i];
    stack<int> stIn;    // 输入栈
    for(int i = 0; i < n; ++i){
        stIn.push(nums[i]);
    }
    push(stIn);
    while(!stOut.empty()){
        cout << stOut.top() << " " ;
        stOut.pop();
    }
    return 0;
}


发表于 2022-04-07 13:02:49 回复(0)
import java.util.*;
public class Main{
    
    public static void main(String[] args){
        
        Scanner sc = new Scanner(System.in);
        
        int n = sc.nextInt();
        Stack<Integer> stackA = new Stack<Integer>();
        Stack<Integer> stackB = new Stack<Integer>();
        while(sc.hasNextInt()){
            stackA.push(sc.nextInt());
        }
        while(!stackA.isEmpty()){
            int temp=stackA.pop();
            while( !stackB.isEmpty() && stackB.peek()>temp){
                stackA.push(stackB.pop());
            }
            stackB.push(temp);
        }
        while(!stackB.isEmpty()){
            System.out.print(stackB.pop()+" ");
        }
    }
}

发表于 2022-01-17 16:42:09 回复(0)
# 输入的元素个数
n = int(input())
# 用列表模仿栈
stack = []
number = input().split()
number.reverse()
for i in range(len(number)):
    stack.append(int(number[i]))
# 辅助的栈
help = []
while len(stack) != 0:
    a = stack.pop()
    while len(help) != 0 and help[-1] < a:
        stack.append(help.pop())
    help.append(a)
while len(help) != 0:
    stack.append(help.pop())
# 输出栈顶到栈底
for i in range(len(stack)):
    print(stack.pop(), end=' ')
《程序员代码面试》Python题解 https://zhuanlan.zhihu.com/p/444550262
发表于 2021-12-26 08:05:51 回复(0)
用了递归,实现的比题解复杂太多...555不亏是我,fw
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Scanner;
import java.util.Stack;

/**
 * @author hugh
 * @create 2021-09-04 23:10
 */
public class Main {
    public static void main(String[] args) throws IOException {
        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
        int n = Integer.parseInt(in.readLine());
        String[] line = in.readLine().split(" ");
        Stack<Integer> data = new Stack<>();
        for (int i = n - 1; i >= 0; i--) {
            data.push(Integer.parseInt(line[i]));
        }
        Stack<Integer> stack = new Stack<>();
        sort(data, stack);
        StringBuilder res = new StringBuilder();
        while (!data.isEmpty()) {
            res.append(data.pop() + " ");
        }
        System.out.println(res.substring(0, res.length() - 1));
    }

    public static void sort(Stack<Integer> data, Stack<Integer> stack) {
        while (!data.isEmpty()) {
            Integer num1 = data.pop();
            put(stack, num1);
        }

        while (!stack.isEmpty()) {
            data.push(stack.pop());
        }
    }

    /**
     * 将x插入data中的合适位置,保证从大到小的顺序
     * @param stack 按照从大到小(栈底->栈顶)排序的栈
     * @param x  整数
     */
    public static void put(Stack<Integer> stack, Integer x) {
        if (stack.isEmpty() || stack.peek() > x) {
            stack.push(x);
        } else {
            Integer num = stack.pop();
            put(stack, x);
            stack.push(num);
        }
    }
}



发表于 2021-09-04 23:45:50 回复(0)
C++,可以通过。
#include<iostream>
#include<stack>
#include<vector>
#include<algorithm>
using namespace std;
int main()
{
    int N,x;
    cin>>N;
    stack<int> stack1,stack2;
    for(int i=0;i<N;++i){
        cin>>x;
        stack1.push(x);
    }
    while(!stack1.empty()){
        int cur=stack1.top();
        stack1.pop();
        while(!stack2.empty() && cur>stack2.top()){
            stack1.push(stack2.top());
            stack2.pop();
        }
        stack2.push(cur);
    }
    while(!stack2.empty()){
        stack1.push(stack2.top());
        stack2.pop();
    }
    for(int i=0;i<N;++i){
        cout<<stack1.top()<<" ";
        stack1.pop();
    }
}


发表于 2021-07-14 10:29:41 回复(0)

十一点吃个🍎 👉🏻map竟然忘记返值

let line=readline()
let stack=[],help=[]
while(line=readline()){
    stack=line.split(' ')

   stack= stack.map(item=>parseInt(item))
//     console.log(stack)
    while(stack.length){
        let cur=stack.pop()
        if(help.length==0||help[help.length-1]<cur){
            help.push(cur)
        }else{
            while(help.length){
                var helpcur=help[help.length-1]
                if(helpcur>cur){
                    stack.push(help.pop())
                }else break                   
            }
            help.push(cur)
        }
    }
    console.log(help.reverse().join(' '))
}
发表于 2021-06-24 23:22:06 回复(0)
#include <iostream>
#include <stack>
using namespace std;

void mySort(stack<int> &st){
    stack<int> help;
    while(!st.empty()){
        int val = st.top();
        st.pop();
        while(!help.empty() && val > help.top()){
            st.push(help.top());
            help.pop();
        }
        help.push(val);
    }
    while(!help.empty()){
        st.push(help.top());
        help.pop();
    }
}

int main(void){
    int N;
    cin >> N;
    int val;
    stack<int> st;
    for(int i = 0; i < N; i++){
        cin >> val;
        st.push(val);
    }
    mySort(st);
    while(!st.empty()){
        cout << st.top() << " ";
        st.pop();
    }
    cout << endl;
    return 0;
}
解决问题如下:
1. 用一个栈存 如果比他小的话,直接就压回原栈,不保存。但代码不好,不如直接用count标记
发表于 2021-04-22 10:10:12 回复(0)
        本题可以使用一种类似单调栈的思想,即保证每次栈1插入元素后,栈1都保持由小到大的顺序,这里为了保证栈1的顺序,利用栈2作为中转栈暂存其值。
#include <iostream>
#include <stack>
using namespace std;

int main(){
    int N=0, val=0;
    cin >> N;
    stack<int> st1, st2;
    while(N--){  //每次插入数据后,都要保证st1的顺序。
        cin >> val;
        while(!st1.empty() && st1.top()>val){ //当前栈不空,并且栈顶元素大于要插入的元素。
            st2.push(st1.top());
            st1.pop();
        }
        st1.push(val);
        while(!st2.empty()){
            st1.push(st2.top());
            st2.pop();
        }
    }
    while(!st1.empty()){
        cout << st1.top() << " ";
        st1.pop();
    }
    return 0;
}


发表于 2020-11-03 18:18:02 回复(0)

解题思路:
遍历给定的栈,将当前的栈中的元素压入辅助栈中,当压入辅助栈的序列不是递增序列时,就把辅助栈中的元素重新压入原来的栈,直到辅助栈的序列为递归序列。

/*
 * @Description: 用一个栈实现另一个栈的排序
 * @Author: 
 * @Date: 2020-10-27 16:03:00
 * @LastEditTime: 2020-10-27 16:27:22
 * @LastEditors: Please set LastEditors
 */
#include<iostream>
#include<stack>
using namespace std;

int main(){

    int N, num;
    cin >> N;
    stack<int> s1; //表示第一个栈
    stack<int> s2; //表示第二个栈
    for(int i = 0;i < N;i++){
        cin >> num;
        s1.push(num);
    }
    while(!s1.empty()){
        s2.push(s1.top());
        s1.pop();
    }
    //此时s2中的从栈顶到栈底的元素与输入的元素一致
    //下面为用s1将s2进行排序
    while(!s2.empty()){
        int temp = s2.top();
        s2.pop();
        while(!s1.empty() && temp < s1.top()){
            s2.push(s1.top());
            s1.pop();
        }
        s1.push(temp);
    }
    //输出s1
    while(!s1.empty()){
        cout << s1.top() << " ";
        s1.pop();
    }
    //system("pause");
    return 0;
}
编辑于 2020-10-27 16:43:05 回复(0)