剑指offer:包含min函数的栈

题目描述

定义栈的数据结构,请在该类型中实现一个能够得到栈中所含最小元素的min函数(时间复杂度应为O(1))。

 

要求以时间复杂度为O(1)来得到栈中的最小元素,那就要保证最小元素一直在栈顶,这样才可以随时弹出。如果在原本的栈中操作,这样就不能保证栈中最后进入的元素最先被弹出了,因此我们需要借助外部空间来进行操作。

如果我们定义一个变量min来表示最小元素,每当压入栈一个元素,都将这个元素和最小元素进行比较,如果比min下,就更新min为当前这个元素,min中存放的是当前栈中最小的元素,但是会有一个问题,如果栈中这个min对应的元素被弹出了,那此时min的值就不能表示新栈中的最小元素值了,因此不能用变量定义。

建立一个新的临时栈用来存储当前栈中的最小元素,每当入栈一个新的元素,都将这个元素和min栈中的元素进行比较,如果比它小,则将这个元素也压入min栈。这样min栈的顶部弹出的永远都是当前栈中最小的元素。

存入min栈的元素有两种方式,

方式1:

如果当前要压入栈的元素比min栈存储的最小值小,则将这个元素压入min栈,否则,将min栈中的最小值重新压入min栈。

剑指offer:包含min函数的栈

剑指offer:包含min函数的栈

方式2:

如果当前要压入栈的元素比min栈存储的最小值小,则将这个元素压入min栈,否则,min栈不做更新,不存入任何新数据。

剑指offer:包含min函数的栈

对于数据栈,这操作都方式都是一样的,对于min栈,两种不同的操作方式,区别是:

对于方式1:每当新元素入栈,min栈也会同步增加min值,保持数据栈和辅助栈的长度是一致的,这样在pop的时候,对于数据栈和辅助栈,只需要同时pop就可以。

对于方式2:只有在新元素比min栈中的min小的时候才将它压入min栈,否则,min栈不进行任何操作,这样的话,在pop的时候就需要判断当前pop的值是否是min栈中栈顶的值,如果是,min栈也pop,否则,只对数据栈pop。

方式2 的优势是,数据栈新元素入栈和栈顶元素出栈时,min栈会少操作几步压入和弹出操作。缺点是,弹出需要做判断。

而方式1的弹出不用做任何判断,保持同步就行。

代码1:

package com.day01;
import java.util.Stack;
public class MinInStack {
	/*思路:需要借助一个辅助栈来存放最小元素。
	 * 每次压入一个新元素进栈的时候,如果该元素比当前最小的元素还要小,则更新最小元素。
	 * 但是如果当前最小的元素被弹出了,怎么得到下一个最小的元素是一个问题,
	 * 因此只添加一个成员变量存放最小元素是不够的,即当最小元素被弹出时,我们希望能够的得到次小的元素。
	 * 因此在压入最小元素之前,我们要把次小的元素保存起来。因此可以借助一个辅助栈把每次的最小元素保存起来*/
	
	Stack<Integer> data=new Stack<>();//存放元素栈
	Stack<Integer> min=new Stack<>();//辅助栈,data栈中每次进入一个元素,min辅助栈就存放当前data栈中的最小元素
	//data栈和min栈进入元素
	public void push(int node){
		data.push(node);
		if(min.size()==0||node<min.peek()){
			min.push(node);
		}else{
			min.push(min.peek());
		}	
	}
	//data栈和min栈中弹出元素
	public void pop(){
		if(data.size()>0&&min.size()>0){
			data.pop();
			min.pop();
		}
	}
	//data栈的栈顶元素
	public int top(){
		if(data.size()>0){
			return data.peek();
		}
		return 0;
	}
	//min栈的栈顶元素,栈顶元素为data栈中现有元素的最小元素
	public int min(){
		if(data.size()>0&&min.size()>0){
			return min.peek();
		}
		
		return 0;
		
	}

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		MinInStack mis=new MinInStack();
		mis.push(3);
		mis.push(2);
		mis.push(4);
		mis.push(3);
		System.out.println(mis.min());

		

	}

}

代码2:

package com.day01;
import java.util.Stack;

public class MinInStack2 {
	Stack<Integer> data=new Stack<>();
	Stack<Integer> min=new Stack<>();
	 public void push(int node) {
		 data.push(node);
		 if(min.size()==0||node<min.peek()){
			 min.push(node);
		 }
	        
	    }
	    
	 public void pop() {
		 if(data.size()>0&&min.size()>0){
			 int peek=data.peek();
			 data.pop();
			 if(peek==min.peek()){
				 min.pop();
			 }
		 }
	        
	    }
	    
	 public int top() {
		if(data.size()>0){
			return data.peek();
		}
		return 0;
	        
	    }
	    
	 public int min() {
		if(min.size()>0){
			return min.peek();
		}
		return 0;
	        
	    }
	 public static void main(String[] args) {
			// TODO Auto-generated method stub
			MinInStack mis=new MinInStack();
			mis.push(3);
			mis.push(2);
			mis.push(4);
			mis.push(3);
			System.out.println(mis.min());
	 }
}

 

参考:

https://blog.csdn.net/jsqfengbao/article/details/47260355