栈操作编程题


这几天在网上找了几道关于栈的编程题,在这里总结一下

1.请编写一个程序,按升序对栈进行排序(即最大元素位于栈顶),要求最多只能使用一个额外的栈存放临时数据,但不得将元素复制到别的数据结构中。

给定一个int[] numbers,其中第一个元素为栈顶,请返回排序后的栈。请注意这是一个栈,意味着排序过程中你只能访问到第一个元素。

测试样例:
[1,2,3,4,5]
返回:[5,4,3,2,1]


 
 

思路:首先需要创建两个栈initStack初始化栈和tempStack临时栈,这两个栈分别存放着待排序列和已排序列,

(1)先将元素进行入栈操作,全部入栈到initStack栈中

(2)若tempStack中元素为空,将initStack中的元素出栈并入栈到tempStack

(3)创建一个临时元素temp(即待排元素)来存放着initStack中的栈顶元素

(4)将tempStack中比temp大的元素依次出栈到initStack中(此时tempStack中的元素都比temp小,且有序),将temp进行入栈操作,入栈到tempStack

import java.util.ArrayList;
import java.util.Stack;

public class TwoStacks {
    public ArrayList<Integer> twoStacksSort(int[] numbers) {
        // write code here

        ArrayList<Integer> list = new ArrayList<Integer>();

        //创建两个栈
        //initStack为初始化栈,存放着待排序列
        //tempStack为临时栈,存放着已排序列
        Stack<Integer> initStack = new Stack<>();
        Stack<Integer> tempStack = new Stack<>();
        //将initStack进行初始化操作,将元素进行入栈
        for(int i = 0;i < numbers.length;i++)
        {
            initStack.push(numbers[i]);
        }
        while(!initStack.isEmpty())
        {
            if(tempStack.isEmpty())
            {
                //若临时栈tempStack为空,将初始化栈中的元素出栈,并入栈到临时栈中
                tempStack.push(initStack.pop());
            }
            else
            {
                //临时栈tempStack不为空
                //创建一个临时元素放置着待排元素(从初始化栈出栈的元素)
                int temp = initStack.pop();
                while(!tempStack.isEmpty() && tempStack.peek() > temp)
                {
                    //若临时栈tempStack不为空,或者临时栈的栈顶元素大于临时元素,
                    // 就将临时栈tempStack中的元素出栈到初始化栈中
                    initStack.push(tempStack.pop());
                }
                //若临时栈tempStack为空,或者临时栈的栈顶元素不大于临时元素,
                //就将临时元素入栈到临时栈中
                tempStack.push(temp);
            }
        }
        //最后将临时栈中元素加到list中
        while(!tempStack.isEmpty())
        {
            list.add(tempStack.pop());
        }
        return list;
    }
}
2.请实现一种数据结构SetOfStacks,由多个栈组成,其中每个栈的大小为size,当前一个栈填满时,新建一个栈。该数据结构应支持与普通栈相同的push和pop操作。

给定一个操作序列int[][2] ope,每个操作的第一个数代表操作类型,若为1,则为push操作,后一个数为应push的数字;若为2,则为pop操作,后一个数无意义。请返回一个int[][](C++为vector&ltvector&ltint>>),为完成所有操作后的SetOfStacks,顺序应为从下到上,默认初始的SetOfStacks为空。保证数据合法。

思路:创建两个栈队列curList当前栈,stackList栈队列,通过使用switch...case来实现

(1)当case为1时表示入栈,先判断当前栈curList是否已满

        1)若curList未满,直接入站

        2)若curList已满,将curList栈先入stackList,然后再进行入站

(2)当case为2时表示出栈:先判断当前栈是否为空

        1)若curList不为空,直接将栈中元素弹出,进行出栈

        2)若curList为空,先从stackList出栈,再从curList出栈

public class SetOfStacks {
    public ArrayList<ArrayList<Integer>> setOfStacks(int[][] ope, int size) {
        // write code here
        //栈队列
        ArrayList<ArrayList<Integer>> stackList = new ArrayList<ArrayList<Integer>>();
        //当前栈
        ArrayList<Integer> curList = new ArrayList<Integer>(size);
        //先将当前栈进行入栈
        stackList.add(curList);
        for(int i = 0; i < ope.length ; i++)
        {
            switch(ope[i][0])
            {
                //1为入栈
                case 1:
                    if(curList.size() != size)
                    {
                        //若栈未满,直接进行当前栈的入栈操作
                        curList.add(ope[i][1]);
                    }
                    else
                    {
                        //当前栈已满,先将当前栈入总栈,再入当前栈
                        curList = new ArrayList<Integer>(size);
                        stackList.add(curList);
                        curList.add(ope[i][1]);
                        //注:此处不能开辟新的栈空间,下面这种写法不对
                        //ArrayList<Integer> newList = new ArrayList<Integer>(size);
                    }
                    break;//此处要break跳出

                    //2出栈
                case 2:
                    if(curList.size() != 0)
                    {
                        //当前栈的大小不为0,说明栈中还有元素,直接出栈
                        curList.remove(curList.size() - 1);
                    }
                    else
                    {
                        //当前栈为空,先将总栈出栈,再从当前栈进行出栈操作
                        stackList.remove(stackList.size() - 1);
                        curList = stackList.get(stackList.size() - 1);
                        curList.remove(curList.size() - 1);
                        //注:此处不能开辟新的栈空间,下面这种写法不对
                        //ArrayList<Integer> newList = stackList.get(stackList.size() - 1);
                    }
                    break;
            }
        }
        return stackList;
    }
}

3.输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如序列1,2,3,4,5是某栈的压入顺序,序列4,5,3,2,1是该压栈序列对应的一个弹出序列,但4,3,5,1,2就不可能是该压栈序列的弹出序列。(注意:这两个序列的长度是相等的)

思路:创建一个栈Stack

(1)将压入序列的第一个元素先压入栈中(以题目为例,此时为1),此时与弹出序列的第一个元素4比较,不相等,那么再将压入序列的第二个元素压入栈Stack中,再依次与出栈序列的第一个元素作比较

(2)当压入1,2,3,4之后,发现此时4与出栈序列的第一个元素4相等,此时将Stack的栈顶元素4出栈,再将出栈队列的判断元素向后移一位,

(3)此时Stack栈中元素为1,2,3,要判断元素为5,不相等,再将后面的元素继续入栈Stack

(4)与(2)判断操作相同,出栈之后,Stack栈中还有1,2,3,而要判断的元素为3,相等,将Stack的栈顶元素出栈,依次反复,最终两个序列的元素都为空,判断结束

import java.util.Stack;

public class Solution {
    public boolean IsPopOrder(int [] pushA,int [] popA) {
        if(pushA.length == 0 || popA.length == 0 || pushA.length != popA.length)
        {
            return false;
        }
        Stack <Integer> stack = new Stack<Integer>();
        int popIndex = 0;
        for(int i = 0;i < pushA.length;i++)
        {
            stack.push(pushA[i]);
            while(!stack.empty() && stack.peek() == popA[popIndex])
            {
                stack.pop();
                popIndex++;
            }
        }
        return stack.empty();
    }
}

4.定义栈的数据结构,请在该类型中实现一个能够得到栈中所含最小元素的min函数。

思路:首先创建两个栈,一个是放置数据的栈dataStack,另一个是放置最小元素的栈minStack

(1)入栈push()操作:将元素入栈到dataStack,对于minStack栈,若minStack中为空,或者栈顶元素大于要入栈元素,则直接将元素入栈到minStack

(2)出栈pop()操作:直接将两个栈中的元素出栈

(3)取栈顶元素top():取出minStack的栈顶元素

(4)取最小元素min():由于之前在入栈操作时已经将最小元素入栈到minStack的栈顶,因此最小元素只需取出minStack的栈顶元素即可

public class Solution {
    Stack<Integer> datastack = new Stack<Integer>();
    Stack<Integer> minStack = new Stack<Integer>();

    public void push(int node)
    {
        datastack.push(node);

        if(minStack.isEmpty() || minStack.peek() > node)
        {
            //若minStack栈中没有元素或者minStack的栈顶元素大于要入栈的元素
            //直接将元素入栈
            minStack.push(node);
        }
        else
        {
            minStack.push(minStack.peek());
        }
    }

    public void pop()
    {
        datastack.pop();
        minStack.pop();
    }

    public int top()
    {
        return datastack.peek();
    }

    public int min()
    {
        return minStack.peek();
    }
}

5.用两个栈来实现一个队列,完成队列的Push和Pop操作。 队列中的元素为int类型。

思路:栈的出入栈方式为先入后出,而队列的出入方式为先入先出

(1)使用两个栈,stack1和stack2

(2)入队列同入栈,将元素全部入栈到stack1中

(3)出队列操作:由(2)将元素全部入栈到stack1,再将元素全部出栈到stack2中,再将元素全部出栈,此时的顺序为出队列的顺序

public class Solution {
    Stack<Integer> stack1 = new Stack<Integer>();
    Stack<Integer> stack2 = new Stack<Integer>();

    public void push(int node) {
        stack1.push(node);
    }

    public int pop() throws Exception {
        if(stack1.isEmpty() && stack2.isEmpty())
        {
            throw new Exception("Queue is empty");
        }
        if(stack2.isEmpty())
        {
            while (!stack1.isEmpty())
            {
                stack2.push(stack1.pop());
            }
        }
        return stack2.pop();

    }
}
6.堆栈是一种基本的数据结构。堆栈具有两种基本操作方式,push 和 pop。Push一个值会将其压入栈顶,而 pop 则会将栈顶的值弹出。现在我们就来验证一下堆栈的使用。
输入描述:
     对于每组测试数据,第一行是一个正整数 n,0<n<=10000(n=0 结束)。而后的 n 行,每行的第一个字符可能是'P’或者'O’或者'A’;如果是'P’,后面还会跟着一个整数,表示把这个数据压入堆栈;如果是'O’,表示将栈顶的值 pop 出来,如果堆栈中没有元素时,忽略本次操作;如果是'A’,表示询问当前栈顶的值,如果当时栈为空,则输出'E'。堆栈开始为空。
输出描述:
    对于每组测试数据,根据其中的命令字符来处理堆栈;并对所有的'A’操作,输出当时栈顶的值,每个占据一行,如果当时栈为空,则输出'E’。当每组测试数据完成后,输出一个空行。

输入

3
A
P 5
A
4
P 3
P 6
O 
A

输出

E
5

3

思路:创建一个数组来存放第一行的整数

(1)将第一个输入的元素下标设为top,初始值为0,创建字符ch

(2)若ch接收到的字符为P时,将下标向后移动,再输入下一个字符

(3)若ch接收到的字符为O时,若top>0(即数组中不止一个元素),则向前移动一个字符,

(4)若ch接收到的字符为A时,此时top为0,就直接输出字符E,若不为0,就输出top之前的一个元素

public class Solution {
    static int[] nums = new int[1000];
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        while (scanner.hasNext())
        {
            int n = scanner.nextInt();
            int top = 0;
            while (n-- > 0)
            {
                char ch = scanner.next().charAt(0);
                if(ch == 'P')
                {
                    nums[top++] = scanner.nextInt();
                }
                else if (ch == 'O')
                {
                    if(top > 0)
                    {
                        nums[--top] = 0;
                    }
                }
                else if(ch == 'A')
                {
                    System.out.println(top == 0 ? "E" : nums[top - 1]);
                }
            }
            System.out.println();
        }
    }
}
7.一个栈依次压入1,2,3,4,5那么从栈顶到栈底分别为5,4,3,2,1。将这个栈转置后,从栈顶到栈底为1,2,3,4,5,也就是实现了栈中元素的逆序,请设计一个算法实现逆序栈的操作,但是只能用递归函数来实现,而不能用另外的数据结构。

给定一个栈Stack以及栈的大小top,请返回逆序后的栈。

测试样例:
[1,2,3,4,5],5
返回:[5,4,3,2,1]

思路:在原先的数组上从开始和末尾的元素进行交换,

public class ReverseStack {
    public int[] reverseStackRecursively(int[] stack, int top) {
        // write code here
        if(top <= 0)
        {
            return null;
        }
        recursive(stack,0,top - 1);
        return stack;
    }

    private void recursive(int[] stack, int start, int end) {
        if(start <= end)
        {
            return;
        }
        //交换使用中间量temp不能通过测试用例
        stack[start] ^= stack[end];
        stack[end] ^= stack[start];
        stack[start] ^= stack[end];
        recursive(stack,start + 1,end - 1);
    }

}

猜你喜欢

转载自blog.csdn.net/l_x_y_hh/article/details/80972251