程序员面试金典--题目解析-3.2 设计一个栈,除pop,push方法外,还支持min方法,要求这三个方法的时间复杂度为O(1)

3.2 题目:

 设计一个栈,除pop,push方法外,还支持min方法,要求这三个方法的时间复杂度为O(1)


解法:

1、第一种想法(X):

可以在栈类中加入一个minValue的字段,维护最小值。

入栈时,更新最小值;出栈时,也需要更新最小值。

若最小值被出栈,则需要搜索整个栈,才能找到新的最小值,这不符合O(1)的时间复杂度要求。


2、第二种想法(√):

按照空间换时间的思路,我们可以考虑每次新的元素入栈时,记录下该元素加入以后的新栈对应的最小值。这个最小值被维护在了这个新加入的元素中。

出栈的时候,不需要担心是否把最小值换出,只要找新栈顶维护的最小值即可。

min方法,也只需peek出栈顶元素,得到该元素的min字段即可。


举例说明:

push(5) 栈为{5} 最小值为5,这个最小值被存入了5这个元素对应的min字段中

push(6) 栈为{6,5} 最小值为5,这个最小值被存入了6这个元素对应的min字段中

push(3) 栈为{3,6,5} 最小值为3,这个最小值被存入了3这个元素对应的min字段中

push(7) 栈为{7,3,6,5} 最小值为3,这个最小值被存入了7这个元素对应的min字段中

pop() 弹出7,最小值为栈顶元素3维护的最小值 3

pop() 弹出3,最小值为栈顶元素6维护的最小值 5

......

3、第三种想法(√):

第二种想法有个缺点,当栈很大时,每个元素都要记录min,就会浪费大量的空间。

比如,假如最先入栈的元素是最小值3,后续入栈的元素都比这个值大,那么后续元素维护的最小值都是3,浪费空间。

可以使用另外一个新的栈Stack<Integer>来记录这个最小值,以节省空间,这个新的栈被维护到了StackWithMin这个栈中。


代码如下:

  1. package StackAndQueue;  
  2.   
  3. import java.util.Stack;  
  4.   
  5. public class StackWithMin extends Stack<Integer> {  
  6.     Stack<Integer> s2;  
  7.       
  8.     public StackWithMin(){  
  9.         s2 = new Stack<Integer>();  
  10.     }  
  11.       
  12.     public void push(int value){  
  13.         if(value <= min()){  
  14.             s2.push(value);  
  15.         }  
  16.         super.push(value);  
  17.     }  
  18.       
  19.     public Integer pop(){  
  20.         int value = super.pop();  
  21.         if(value == min()){  
  22.             s2.pop();  
  23.         }  
  24.         return value;  
  25.     }  
  26.       
  27.     public int min(){  
  28.         if(s2.isEmpty()){  
  29.             return Integer.MAX_VALUE;  
  30.         }  
  31.         else{  
  32.             return s2.peek();  
  33.         }  
  34.     }  
  35. }  


测试用例:

  1. @Test  
  2.     public void test_3_2() {  
  3.         StackWithMin stack = new StackWithMin();  
  4.         stack.push(3);  
  5.         System.out.println(stack.min());  
  6.         stack.push(4);  
  7.         System.out.println(stack.min());  
  8.         stack.push(5);  
  9.         System.out.println(stack.min());  
  10.         stack.push(6);  
  11.         System.out.println(stack.min());  
  12.           
  13.         stack.pop();  
  14.         System.out.println(stack.min());  
  15.         stack.pop();  
  16.         System.out.println(stack.min());  
  17.           
  18.         System.out.println();;  
  19.           
  20.         while(!stack.s2.isEmpty()){  
  21.             System.out.println(stack.s2.pop());  
  22.         }  
  23.           
  24.     }  


测试结果:

第三种想法,只存了一个3到s2中

第二种想法,需要存4个3到每个元素中,对比之下,第三种想法更加节省空间。

在栈很大时,优势就很明显了



猜你喜欢

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