实现一个最小栈的push(int x),pop(),top(),min()方法,要求都是常量时间

本文介绍了一种使用单个数组实现最小栈的方法,确保push、pop、top和min操作均能在常数时间内完成。提供了完整的Java代码示例,并通过LeetCode验证。

原题目:https://oj.leetcode.com/problems/min-stack/solution/

实现一个最小栈的push(int x),pop(),top(),min()方法,要求都是常量时间


此代码已经被leetcode接受,下面的分析结果是leetcode给出的:

Hints:

  • Consider space-time tradeoff. How would you keep track of the minimums using extra space?
  • Make sure to consider duplicate elements.
O(n) runtime, O(n) space – Extra stack:

Use an extra stack to keep track of the current minimum value. During the push operation we choose the new element or the current minimum, whichever that is smaller to push onto the min stack.

O(n) runtime, O(n) space – Minor space optimization:

If a new element is larger than the current minimum, we do not need to push it on to the min stack. When we perform the pop operation, check if the popped element is the same as the current minimum. If it is, pop it off the min stack too.

Average Rating: 4.0 (293 votes)


​/**
 * @Author jiangfq
 * 
 */
package com.test;

import java.util.Random;

/**
 * @author jiangfq
 *
 */
public class MinStack {
    
	private static final int INIT_CAPACITY = 16;
	private static final float FACTOR = 0.75f;
	
	private int[] a = null;
	private int currIndex = 0;
	private int size = 0;
	private int min = Integer.MAX_VALUE;
	private int minIndex = -1;
	public MinStack() {
		a = new int[INIT_CAPACITY];
	}
	
	public MinStack(int capacity) {
		if(capacity < 1 || capacity > (Integer.MAX_VALUE - 8)) {
			throw new IllegalArgumentException("illegal capacity value: " + capacity);
		}
		a = new int[capacity];
	}
	
	public void push(int x) {
		if(size > (Integer.MAX_VALUE - 8)) {
			throw new RuntimeException("no more space to store value");
		}
		if(size > 0 && (size + 1) >= a.length) {
			int newSize = (int)(size+size*FACTOR);
			if(newSize > (Integer.MAX_VALUE - 8)) {
				throw new RuntimeException("no more space to store value");
			}
			int[] b = new int[newSize];
			for(int i = 0; i < size; i++) {
				b[i] = a[i];
			}
			a = b;
		}
		if(x < min) {
			min = x;
			minIndex = size;
		}
        a[size++] = x;
        currIndex++;
    }

    public void pop() {
        if(currIndex < 0) {
        	throw new RuntimeException("no more value to pop");
        }
        a[currIndex--] = -1;
        size--;
        System.out.println("size: " + size);
//        System.out.println("currIndex: " + currIndex + ", " + minIndex + ", " + a[currIndex]);
        if(currIndex == minIndex) {
        	int index = 0;
        	int m = a[index];
        	for(int i = (currIndex - 1); i >= 0; i--) {
        		for(int j = i; j >= 0; j--) {
//        			System.out.println("a=" + m + ", " + a[j]);
        			if(m > a[j]) {
        				index = j;
        				m = a[index];
        			}
        		}
        	}
        	min = a[index];
        	minIndex = index;
        }
        if(size == 0) {
        	min = Integer.MAX_VALUE;
        	minIndex = -1;
        }
    }

    public int top() {
    	System.out.println(currIndex+"");
    	return a[currIndex-1];
    }

    public int getMin() {
    	return min;
    }
    public static void main(String[] args) {
    	MinStack ms = new MinStack();
//    	ms.push(2);ms.push(0);ms.push(3);ms.push(0);
//    	System.out.println(+ ms.getMin());
//    	ms.pop();
//    	System.out.println(+ ms.getMin());
//    	ms.pop();
//    	System.out.println(+ ms.getMin());
//    	ms.pop();
//    	System.out.println(+ ms.getMin());
    	
    	ms.push(2147483646);ms.push(2147483646);ms.push(2147483647);
    	System.out.println(ms.top());
    	ms.pop();
    	System.out.println(ms.getMin());
    	ms.pop();
    	System.out.println(ms.getMin());
    	ms.pop();
    	ms.push(2147483647);
    	System.out.println(ms.top());
    	System.out.println(ms.getMin());
    	ms.push(-2147483648);
    	System.out.println(ms.top());
    	System.out.println(ms.getMin());
    	ms.pop();
    	System.out.println(ms.getMin());
    }
    
}

<think>好的,我现在需要解决用户的问题,即在的顺序存储实现中,当Top定义为顶的上一个位置时,如何编写入和出操作,并判断的空和满。首先,我得仔细理解用户的需求和提供的结构定义。 用户给出的Stack结构体中,Top顶的上一个位置。这意味着当为空时,Top的值可能是什么?通常,如果底从数组下标0开始,当Top为0时,可能表示为空,因为下一个可以插入的位置是0,此时还没有元素。例如,如果MaxSize是的最大容量,那么当Top等于MaxSize时,就满了,因为此时数组的最后一个位置是MaxSize-1,已经无法再插入新元素。 接下来,Push操作的逻辑应该是:首先检查是否已满。如果Top等于MaxSize,那么已满,输出提示并返回false。否则,将数据存入Data[Top]的位置,然后Top自增1。例如,假设的最大容量是5,初始时Top为0。当插入第一个元素后,Top变为1,此时一个元素在位置0。当Top达到5时,满,无法继续插入。 Pop操作则需要检查是否为空。如果Top为0,说明没有元素可以弹出,输出提示并返回ERROR。否则,先将Top减1,然后返回Data[Top]的值。例如,如果Top是3,说明当前中有3个元素,位于0、1、2的位置。执行Pop时,Top减到2,返回Data[2]的元素。 关于判断空和满的条件,空的条件是Top == 0,满的条件是Top == S->MaxSize。这样设计的话,每次Push时,Top指向下一个可插入的位置,而中已有的元素数量等于Top的值。因此,当Top等于MaxSize时,表示数组已经填满,无法再添加新元素。 现在需要根据这些逻辑编写代码。注意函数接口的定义,PushPop的参数是Stack S,而Stack是指向SNode的指针。因此,在函数中可以直接访问S的Data、Top和MaxSize字段。 对于Push函数,具体步骤: 1. 检查S->Top是否等于S->MaxSize。如果是,输出Stack Full,返回false。 2. 将X存入S->Data[S->Top]。 3. S->Top自增1。 4. 返回true。 对于Pop函数: 1. 检查S->Top是否为0。如果是,输出Stack Empty,返回ERROR(假设ERROR是一个预定义的常量,比如用INT_MIN表示)。 2. S->Top减1。 3. 返回S->Data[S->Top]。 需要注意的是,ElementType的具体类型未给出,假设为int或其他基本类型。ERROR需要根据实际情况定义,例如可以定义为-1或者使用一个特殊值,但题目中可能要求返回ElementType类型,因此可能需要使用一个不可能出现在中的值,比如如果ElementType是int,可能返回-9999,并在函数外处理这种情况。 另外,用户提供的结构体中,Data是一个ElementType的指针,所以在创建时需要正确分配数组内存,但这个问题可能不在当前函数的实现范围内,因此无需考虑。 现在根据上述分析编写代码: bool Push(Stack S, ElementType X) { if (S->Top == S->MaxSize) { printf("Stack Full\n"); return false; } S->Data[S->Top] = X; S->Top++; return true; } ElementType Pop(Stack S) { if (S->Top == 0) { printf("Stack Empty\n"); return ERROR; // 假设ERROR已定义 } S->Top--; return S->Data[S->Top]; } 这样,当Top指向下一个可用位置时,PushPop操作就能正确工作。判断空是Top为0,满则是Top等于MaxSize。 可能需要注意的边界情况,比如当刚初始化时,Top为0,此时空。当Push到MaxSize次时,Top变为MaxSize,满。此时再Push就会失败。而Pop操作在Top为0时失败,否则正确弹出顶元素。 现在检查是否满足题目中的所有条件: - Push满时输出Stack Full并返回false。 - Pop空时输出Stack Empty并返回ERROR。 - 正确操作Top的位置。 这样应该就正确了。</think><< 在Top指向顶元素的上一个位置时,堆操作实现如下: ```c #include <stdio.h> #include <stdlib.h> #define ERROR -1 // 假设ElementType为int类型 typedef int ElementType; typedef int Position; typedef struct SNode *PtrToSNode; struct SNode { ElementType *Data; Position Top; int MaxSize; }; typedef PtrToSNode Stack; bool Push(Stack S, ElementType X) { /* 当顶指针Top等于最大容量时说明已满 */ if (S->Top == S->MaxSize) { printf("Stack Full\n"); return false; } /* 将元素存入Top位置后Top自增 */ S->Data[S->Top] = X; S->Top++; return true; } ElementType Pop(Stack S) { /* 当Top为0时说明为空 */ if (S->Top == 0) { printf("Stack Empty\n"); return ERROR; } /* 先减Top再取元素 */ S->Top--; return S->Data[S->Top]; } ``` 实现原理: 1. 空条件:`S->Top == 0`,表示没有任何有效元素 2. 满条件:`S->Top == S->MaxSize`,表示数组空间已耗尽 3. Push操作:先存储元素到当前Top位置,再移动顶指针 4. Pop操作:先回退顶指针,再取出对应位置的元素 判断逻辑: - 空检测:Top指针位于数组起始位置(0) - 满检测:Top指针到达数组末尾(MaxSize) >>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值