这几天在网上找了几道关于栈的编程题,在这里总结一下
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<vector<int>>),为完成所有操作后的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);
}
}