程序员面试金典--题目解析-3.3 实现数据结构SetOfStacks,维护多个栈

3.3 题目:

基础:

设想有一堆盘子,堆太高可能会倒下来。因此在现实生活中,盘子堆到一定高度后,我们会另外堆一堆盘子。

请实现数据结构SetOfStacks,模拟这种行为。SetOfStacks由多个栈组成,并且在前一个栈填满时新建一个栈。

此外,SetOfStacks的push和pop方法应和普通栈逻辑相同,即push加入到最新栈,pop从最新的栈弹出。


进阶:

实现一个popAt(int index) 方法,根据指定的子栈,进行pop操作。


解法:

基础:

  1. package StackAndQueue;  
  2.   
  3. import java.util.ArrayList;  
  4. import java.util.Stack;  
  5.   
  6. public class SetOfStacks<E> {  
  7.     //用于记录所维护的所有Stack  
  8.     private ArrayList<Stack<E>> list = new ArrayList<>();  
  9.     //记录最新的Stack,待存入和取值的Stack  
  10.     private Stack<E> currentStack;  
  11.     //每个栈的最大容量  
  12.     private static final int MAX_CAP = 100;   
  13.       
  14.     public SetOfStacks(){  
  15.         Stack<E> stack = new Stack<>();  
  16.         list.add(stack);  
  17.         currentStack = stack;  
  18.     }  
  19.       
  20.     public void push(E value){  
  21.         if(currentStack.size() >= MAX_CAP){  
  22.             Stack<E> newStack = new Stack<>();  
  23.             newStack.push(value);  
  24.             list.add(newStack);  
  25.             currentStack = newStack;  
  26.         }  
  27.         else{  
  28.             currentStack.push(value);  
  29.         }  
  30.     }  
  31.       
  32.     public E pop(){  
  33.         E value = currentStack.pop();;  
  34.         if(currentStack.size() == 0 && list.size() > 1){  
  35.             list.remove(currentStack);  
  36.             currentStack = list.get(list.size()-1);  
  37.         }  
  38.         return value;  
  39.     }  
  40.       
  41.     public E peek(){  
  42.         if(isEmpty()){  
  43.             return null;  
  44.         }  
  45.         return currentStack.peek();  
  46.     }  
  47.   
  48.     public boolean isEmpty() {  
  49.         return list.size() ==1 && currentStack.size() == 0;  
  50.     }  
  51. }  


测试用例:

  1. @Test  
  2.     public void test_3_3() {  
  3.         SetOfStacks<Integer> setOfStacks = new SetOfStacks<>();  
  4.         for(int i = 0 ;i<201;i++){  
  5.             setOfStacks.push(i);  
  6.         }  
  7.         System.out.println(setOfStacks.peek());  
  8.           
  9.         System.out.println(setOfStacks.pop());  
  10.     }  

使用debug加入断点调试,查看setOfStacks的组成情况即可。


进阶问题解法:

有两种情况

一是待删除的元素就在最新的栈中,那么直接删除即可

二是待删除的元素在前面已经装满的栈中,假如有 0 1 2 三个栈,删除0中的栈顶元素,要保持装入的顺序不变,就需要把1中的栈底元素弹出压入0的栈顶,再把2的栈底元素弹出压入1的栈顶,如果栈的数目更多,依次类推即可,这样操作的目的是保证前面的栈都是满的。

另外,还要注意,进行完情况二的移位之后,若最新栈(currentStack)没有元素了,要从list中删除。

  1. public E popAt(int index){  
  2.         if(index > list.size()-1){  
  3.             return null;  
  4.         }  
  5.         Stack<E> stack = list.get(index);  
  6.         E value = stack.pop();  
  7.         //如果选中的子栈是当前最新子栈  
  8.         if(stack == currentStack){  
  9.             //如果子栈前面还有满子栈,且该子栈弹出后没有元素,从list中删除  
  10.             if(currentStack.size() == 0 && list.size() > 1){  
  11.                 list.remove(currentStack);  
  12.             }  
  13.         //不是当前最新子栈,是前面的满子栈  
  14.         }else{  
  15.             //从待删除子栈开始循环,使用下一个stack的copyInto方法把栈中元素复制到数组中,再取栈底元素压入  
  16.             //待删除子栈,然后删除下一个stack中的栈底元素(使用listIterator的remove方法)  
  17.             for(int i=index;i < list.size()-1;i++){  
  18.                 Stack<E> s = list.get(i);  
  19.                 Stack<E> next = list.get(i+1);  
  20.                 Object[] array = new Object[next.size()];  
  21.                 next.copyInto(array);  
  22.                 s.push((E) array[0]);  
  23.                 Iterator<E> itr = next.listIterator(0);  
  24.                 if(itr.hasNext()){  
  25.                     itr.next();  
  26.                     itr.remove();  
  27.                 }  
  28.             }  
  29.             //这里判断移位后最新子栈是否没有数据  
  30.             if(currentStack.size() == 0){  
  31.                 list.remove(currentStack);  
  32.             }  
  33.         }  
  34.         return value;  
  35.     }  

测试用例:

  1. @Test  
  2.     public void test_3_3_Advance(){  
  3.         SetOfStacks<Integer> setOfStacks = new SetOfStacks<>();  
  4.         for(int i = 0 ;i<201;i++){  
  5.             setOfStacks.push(i);  
  6.         }  
  7.         setOfStacks.popAt(0);  
  8.     }  


可以把201改成250 进行第二次测试。



猜你喜欢

转载自blog.csdn.net/kingmore96/article/details/80092062