Cracking the coding interview--Q3.2

本文介绍了一种特殊栈的设计方案,该栈除基本操作外还能在常数时间内返回最小元素。通过使用辅助栈来跟踪最小值,确保所有操作的时间复杂度均为O(1)。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目

原文:

How would you design a stack which, in addition to push and pop, also has a function min which returns the minimum element? Push, pop and min should all operate in O(1) time.

译文:

设计一个栈,除了push和pop方法外,还有一个min的函数能够返回最小的元素,并且push,pop,min的时间复杂度都为O(1)

解答

首先想到找出栈中最小元素,可以通过每push一个值就作比较,从而得出最小元素,但一旦最小元素在栈顶,执行了pop方法,最小元素出栈,那么就无法在O(1)的时间内找到最小值了,显然这种方法是不可行的。所以,可以考虑每一个元素维护一个指向从当前元素到栈底元素的最小值的指针,如下面例子:



不过可以发现这样存储,浪费很多空间,因此,可以引入另外一个栈S,当每次入栈或者出栈的时候,都通这个额外栈的栈顶元素比较一下。入栈的时候,如果入栈元素大于S栈顶元素,S栈顶元素不变。否则,将入栈元素也压入到栈S中,使栈S保持一个局部的最小值;出栈的时候,如果出栈元素大于S栈顶元素,S栈顶元素不变。否则,将S栈的栈顶元素也一同出栈。

以下是利用LinkedList的栈结构来实现具有min()的栈的:

import java.util.*;

class Q3_2{
	public static void main(String[] args) {
		StackWithMin1 s1 = new StackWithMin1();
		StackWithMin2 s2 = new StackWithMin2();
		int[] arr = new int[]{6,3,4,6,9,1};
		for(int i=0;i<arr.length;i++){
			s1.push(arr[i]);
			s2.push(arr[i]);
		}
		System.out.println(s1.min());
		System.out.println(s2.min());
		s1.pop();
		s2.pop();
		System.out.println(s1.min());
		System.out.println(s2.min());
	}
}

class StackWithMin1{
	LinkedList<Integer[]> values ;
	public StackWithMin1(){
		values = new LinkedList<Integer[]>();
	}
	
	public int  pop(){
		return values.pop()[0];
	}
	public void push(int val){
		//第一个元素入栈设置初始最小值
		if(values.peek()==null){
			values.push(new Integer[]{val,val});
		}
		int min = values.peek()[1];
		if(min<val){
			values.push(new Integer[]{val,min});
		}else{
			values.push(new Integer[]{val,val});
		}
	}
	public int min(){
		int min = values.pop()[1];
		return min;
	}
	
}
class StackWithMin2{
	LinkedList<Integer> values;
	LinkedList<Integer> S;//额外栈
	public StackWithMin2(){
		values = new LinkedList<Integer>();
		S = new LinkedList<Integer>();
	}
	public void push(int val ){
		Integer sPeek = S.peek();
		values.push(val);
		if(sPeek==null||val<=sPeek){
			S.push(val);
		}
	}
	public int pop(){
		Integer t = values.pop();
		if(t<=S.peek()){
			S.pop();
		}
		return t;
	}
	public int min(){
		return S.peek();
	}
}

如有更好的方法,还望交流!

---EOF---

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值