转载请注明出处:http://www.cnblogs.com/wuzetiandaren/p/4254348.html
声明:现大部分文章为寻找问题时在网上相互转载,此博是为自己做个记录记录,方便自己也方便有类似问题的朋友,本文的思想也许有所借鉴,但源码均为本人实现,如有侵权,请发邮件表明文章和原出处地址,我一定在文章中注明。谢谢。
题目:定义栈的数据结构,要求添加一个min函数,能够得到栈的最小元素。要求函数min、push以及pop的时间复杂度都是O(1)。
题目分析:
1.可以用另一个临时栈,当元素进栈时,临时栈则保存当该元素进栈时,该栈内元素的最小值,但这多浪费了一个栈的空间,并不是解。
2.网上有人给出了一些思路,只用一个多余的临时变量保存当前栈里的最小值来解决该问题,其核心思想是进栈时利用对临时变量和入栈值进行一些处理,出栈时能够利用当前的临时变量值还原进栈时该变量的原始值以及该元素出栈后临时变量的值。网友http://blog.csdn.net/anchor89/article/details/6055412#comments的文章给我很大的启示,再次深表感谢!
算法设计:
1. push时,候 如果 value >= min, v_push 直接入栈,如果 value < min, 那么入栈的是 2 * value - min, 然后 min = value .
2.pop出时, 如果栈顶的stack[top] >= min 直接出,如果 stack[top] < min 则出现异常,将min作为pop的返回值,另外需要还原前一个最小值: min = 2 * min - stack[top]
事实上,有如下规律: (k为任意整数):
* push(v_push)时:如果 v_push >= min, v_push 直接入栈;如果 v_push < min, 那么入栈的是 k * v_push - min, 然后 min = v_push. top++
* Pop()时:如果栈顶的stack[top] >= min 直接出;如果 stack[top] < min 则将min作为pop的返回值,再还原前一个最小值min =k* min - stack[top]. top--
java 实现源码:
1 package com.interview; 2 3 import java.util.Scanner; 4 5 /**定义栈的数据结构,要求添加一个min函数,能够得到栈的最小元素。 6 * 要求函数min、push以及pop的时间复杂度都是O(1)。 7 * 8 * @param args 9 */ 10 public class _2StackMin { 11 private static int MIN = Integer.MAX_VALUE; //初始化最小元素 12 private static int top = -1; 13 private static int[] stack; 14 private static int temp = MIN; //由于最小元素会在操作的过程中,以此来保存原始最小值 15 public _2StackMin() { 16 super(); 17 } 18 19 public _2StackMin(int size) { 20 super(); 21 this.stack = new int[size]; 22 } 23 24 public static void main(String[] args) { 25 new _2StackMin(5); 26 min(); 27 } 28 29 //返回最小值的函数 30 public static void min(){ 31 boolean flag = true; 32 while(flag){ 33 Scanner scan = new Scanner(System.in); 34 System.out.println("请选择入栈还是出栈:入栈:push 出栈:pop 退出:exit"); 35 String operate = scan.nextLine(); 36 if(operate.equals("push")){ 37 System.out.println("请输入入栈的值:"); 38 int value = scan.nextInt(); 39 MIN = push(value); 40 System.out.println("当前栈里的最小值为:"+MIN); 41 } 42 else if(operate.equals("pop")){ 43 pop(); 44 } 45 else if(operate.equals("exit")){ 46 flag = false; 47 } 48 } 49 } 50 51 //进栈 52 private static int push(int value){ 53 if(top==stack.length-1){ 54 System.out.println("栈已满,请选择出栈操作!"); 55 } 56 else if(value>=MIN){ //如果 v_push >= min, v_push 直接入栈 57 stack[++top] = value; 58 } 59 else{ //入栈的是 2 * v_push - min, 然后 min = v_push 60 stack[++top] = 2*value - MIN; 61 MIN = value; 62 } 63 return MIN; 64 } 65 66 //出栈 67 private static void pop(){ 68 if(top==-1){ 69 System.out.println("栈已空,请选择入栈或退出操作操作!"); 70 return; 71 } 72 else if(stack[top] >= MIN){ //如果栈顶的top >= min 直接出 73 //int stack0 = stack[top]; 74 System.out.println("出栈的是:"+stack[top--]); 75 if(temp!=MIN){ 76 System.out.println("当前栈里的最小值为:"+MIN); 77 } 78 else 79 System.out.println("这已经是最后一个元素!"); 80 } 81 else{ //将min作为pop的返回值,让 min = 2 * min - top 82 System.out.println("出栈的是:"+MIN); 83 MIN = 2*MIN - stack[top]; 84 top--; 85 if(temp!=MIN){ 86 System.out.println("当前栈里的最小值为:"+MIN); 87 } 88 else 89 System.out.println("这已经是最后一个元素!"); 90 } 91 } 92 }
运行结果:
1 请选择入栈还是出栈:入栈:push 出栈:pop 退出:exit 2 push 3 请输入入栈的值: 4 3 5 当前栈里的最小值为:3 6 请选择入栈还是出栈:入栈:push 出栈:pop 退出:exit 7 push 8 请输入入栈的值: 9 5 10 当前栈里的最小值为:3 11 请选择入栈还是出栈:入栈:push 出栈:pop 退出:exit 12 push 13 请输入入栈的值: 14 2 15 当前栈里的最小值为:2 16 请选择入栈还是出栈:入栈:push 出栈:pop 退出:exit 17 push 18 请输入入栈的值: 19 7 20 当前栈里的最小值为:2 21 请选择入栈还是出栈:入栈:push 出栈:pop 退出:exit 22 push 23 请输入入栈的值: 24 1 25 当前栈里的最小值为:1 26 请选择入栈还是出栈:入栈:push 出栈:pop 退出:exit 27 pop 28 出栈的是:1 29 当前栈里的最小值为:2 30 请选择入栈还是出栈:入栈:push 出栈:pop 退出:exit 31 pop 32 出栈的是:7 33 当前栈里的最小值为:2 34 请选择入栈还是出栈:入栈:push 出栈:pop 退出:exit 35 pop 36 出栈的是:2 37 当前栈里的最小值为:3 38 请选择入栈还是出栈:入栈:push 出栈:pop 退出:exit 39 pop 40 出栈的是:5 41 当前栈里的最小值为:3 42 请选择入栈还是出栈:入栈:push 出栈:pop 退出:exit 43 pop 44 出栈的是:3 45 这已经是最后一个元素! 46 请选择入栈还是出栈:入栈:push 出栈:pop 退出:exit 47 pop 48 栈已空,请选择入栈或退出操作操作! 49 请选择入栈还是出栈:入栈:push 出栈:pop 退出:exit 50 exit