腾讯微信面试题--实现时间复杂度为O(1)的栈

来源:互联网 发布:软件工作量估计 编辑:程序博客网 时间:2024/04/29 15:11

原题:实现一个栈,满足min()  pop()  push()方法的时间复杂度都为O(1).( min()返回栈中最小元素 )

 

     思路1:用一个变量minItem记录栈中的最小值,在push()中 每次加入一个item就跟minItem对比,item更小,只item赋给minItem,然后再min() 中直接return  minItem;

 

     这种思路没考虑在pop()过程中,对minItem的影响,当栈顶元素是minItem,执行pop() 后minItem就不知道指向谁了,因为栈只记录最小值而起,至于最小值之前那些大小关系都没记录

 

      正确思路:为了实现更低的时间复杂度,我们都会想到用空间去换时间,所有这里增加一个数组来nextMinItem[index] 元素大小关系。如果当前最小值是 对象 item1 当push进来的item2比 item1更小,且元素个数从原本的a增加到a+1 这时候我们用我们就应该把item2这个更小的item赋给minItem 然后用nextMinItem[a+1] = item1 来记录 item2 后面的次小值,这样一来当item2 这个栈顶被pop()掉的话,我们就可以minItem = nextMinItem[a+1],来恢复minItem。

 

 

代码:

 

Java代码  收藏代码
  1. package 腾讯面试题;  
  2.   
  3. public class Stack {  
  4.     private int itemCount = 0;  
  5.     private Item minItem = null;  
  6.     private Item[] nextMinItem;  
  7.     private Item stackTop = null;  
  8.     private int maxSize = 100;  
  9.   
  10.     public Stack() {  
  11.         nextMinItem = new Item[maxSize];  
  12.     }  
  13.   
  14.     class Item {  
  15.         int Data;  
  16.         Item nextItem;  
  17.   
  18.         public Item(int data) {  
  19.             this.Data = data;  
  20.         }  
  21.   
  22.     }  
  23.   
  24.     public boolean push(Item item) {  
  25.         if (itemCount == maxSize) {  
  26.             System.out.println("栈已满");  
  27.             return false;  
  28.         }  
  29.         itemCount++;  
  30.         if (minItem == null) {  
  31.             minItem = item;  
  32.         } else {  
  33.             if (item.Data < minItem.Data) {  
  34.                 nextMinItem[itemCount] = minItem;  
  35.                 minItem = item;  
  36.             }  
  37.         }  
  38.         item.nextItem = stackTop;  
  39.         stackTop = item;  
  40.           
  41.         return true;  
  42.     }  
  43.   
  44.     public boolean pop() {  
  45.         if (itemCount == 0) {  
  46.             System.out.println("栈是空的,无法出栈");  
  47.             return false;  
  48.         }  
  49.   
  50.         if (stackTop == minItem) {  
  51.             minItem = nextMinItem[itemCount];  
  52.         }  
  53.         stackTop = stackTop.nextItem;  
  54.         itemCount--;  
  55.         return true;  
  56.   
  57.     }  
  58.   
  59.     public Item min() {  
  60.         if (itemCount == 0) {  
  61.             System.out.println("栈是空的,无最小值");  
  62.             return null;  
  63.         }  
  64.         return minItem;  
  65.     }  
  66.   
  67.     /** 
  68.      * @param args 
  69.      */  
  70.     public static void main(String[] args) {  
  71.         // TODO Auto-generated method stub  
  72.         Stack stack = new Stack();  
  73.         stack.push(stack.new Item(5));  
  74.         System.out.println("push:min=" + stack.min().Data+" itemCount="+stack.itemCount);  
  75.         stack.push(stack.new Item(4));  
  76.         System.out.println("push:min=" + stack.min().Data+" itemCount="+stack.itemCount);  
  77.         stack.push(stack.new Item(3));  
  78.         System.out.println("push:min=" + stack.min().Data+" itemCount="+stack.itemCount);  
  79.         stack.push(stack.new Item(2));  
  80.         System.out.println("push:min=" + stack.min().Data+" itemCount="+stack.itemCount);  
  81.         stack.push(stack.new Item(1));  
  82.         System.out.println("push:min=" + stack.min().Data+" itemCount="+stack.itemCount);  
  83.         stack.pop();  
  84.         System.out.println("pop :min=" + stack.min().Data+" itemCount="+stack.itemCount);  
  85.         stack.pop();  
  86.         System.out.println("pop :min=" + stack.min().Data+" itemCount="+stack.itemCount);  
  87.         stack.pop();  
  88.         System.out.println("pop :min=" + stack.min().Data+" itemCount="+stack.itemCount);  
  89.         stack.pop();  
  90.         System.out.println("pop :min=" + stack.min().Data+" itemCount="+stack.itemCount);  
  91.         stack.pop();  
  92.         System.out.println("栈结构为:\n|____1_____|\n|____2_____|\n|____3_____|\n|____4_____|\n|____5_____|\n");  
  93.   
  94.           
  95.     }  
  96. }  

 

 

运行结果:

 

Java代码  收藏代码
  1. push:min=5 itemCount=1  
  2. push:min=4 itemCount=2  
  3. push:min=3 itemCount=3  
  4. push:min=2 itemCount=4  
  5. push:min=1 itemCount=5  
  6. pop :min=2 itemCount=4  
  7. pop :min=3 itemCount=3  
  8. pop :min=4 itemCount=2  
  9. pop :min=5 itemCount=1  
  10. 栈结构为:  
  11. |____1_____|  
  12. |____2_____|  
  13. |____3_____|  
  14. |____4_____|  
  15. |____5_____|  

 

 

博友thihy的另一种方法:

把nextMinItem嵌入Node中,这样就不需要限制maxSize。

Java代码   收藏代码
  1. class Node{  
  2.    T data;  
  3.    Node min;  
  4.    Node pre;  
  5.    Node(T data, Node pre){  
  6.      this.data = data;   
  7.      this.pre = pre;  
  8.      // 更新目前为止最小的元素(包括自己)  
  9.      if(pre!=null && pre.min.data <= data){  
  10.         this.min = pre.min;  
  11.       }else{  
  12.          this.min = this;  
  13.       }  
  14.    }  
  15. }  


使用top来保存顶点

Java代码   收藏代码
  1. Node top;  


则push、pop和min分别为

Java代码   收藏代码
  1. void push(T data){  
  2.   top = new Node(data=data,pre=top);  
  3. }  
  4. T pop(){  
  5.    assert top!= null;  
  6.    T result = top.data;  
  7.    top = top.pre;  
  8.    return result;  
  9. }  
  10.   
  11. T min(){  
  12.    assert top!=null;  
  13.    return top.min.data;  
  14. }  

 

原创粉丝点击