在O(1)找到栈中的最小值

定义栈的数据结构,请在该类型中实现一个能够得到栈的最小元素的min函数。
在该栈中,调用min、push及pop的时间复杂度都是O(1).


push和pop本来都是O(1),这个不需要担心,但是获取最小值的话, 

如果在栈里添加一个成员变量存放最小的元素。每次压入一个新元素进栈的时候,如果该元素比当前最小的元素还要小,则更新最小元素。
但是如果当前最小的元素被弹出栈了,如何得到下一个最小的元素呢?
分析到这里,我们发现仅仅添加一个成员变量存放最小元素是不够的,仅仅一个变量不够,也需要一个集合类型来存放这个最小元素组成的一组数据 , 也就是说当最小元素被弹出栈的时候,我们希望能够得到次小元素。因此在压入这个最小元素之前,我们要把次小元素保存起来。
保存旧值,保存历史值, 是不是可以想到又是一个栈结构, 把每次的最小元素(之前的最小元素和新压入栈的元素两者的较小值)都保存起来放到另外一个辅助栈.

好,来试一试. 这个新的结构内部有2个栈, 一个主栈,一个辅助栈.
当push的时候,主栈正常push此元素, 辅助栈push 辅助栈顶和此元素中的较小值,
当pop的时候, 主栈pop栈顶, 辅助栈也pop出栈顶元素,
当min的时候, 返回辅助栈的栈顶元素.

来个例子,
push(3),主栈和辅助栈栈顶都是3,
push(5),主栈栈顶放入5,辅助栈放入 辅助栈顶3和5的较小值 , 还是3,
push(7),主栈栈顶放入7,辅助栈放入 辅助栈顶3和7的较小值 , 还是3,
push(1),主栈栈顶放入1,辅助栈放入 辅助栈顶3和1的较小值 , 放入1,
....
当pop的时候, 主栈和辅助栈都执行pop,
...
当min的时候, 返回辅助栈的栈顶元素.

到此, 思路就完成了. 代码量不大, 但是思路很巧妙.

#import <Foundation/Foundation.h>

@interface MinStack : NSObject

- (void)push:(int)data;
- (int)pop;
- (int)min;

@end

-------------

#import "MinStack.h"

@interface MinStack ()

@property (nonatomic, strong) NSMutableArray<NSNumber *> *dataArray;
@property (nonatomic, strong) NSMutableArray<NSNumber *> *minArray;

@end

@implementation MinStack

- (instancetype)init
{
    self = [super init];
    if (self) {
        _dataArray = [NSMutableArray array];
        _minArray = [NSMutableArray array];
    }
    return self;
}

// 主栈进行正常的push, 辅助栈栈push一个当前的最小值
- (void)push:(int)data {
    
    [self.dataArray addObject:@(data)];
    
    int minValue = data ;
    if (self.minArray.count>0) {
        minValue = MIN(data, self.minArray.lastObject.intValue);
    }
    [self.minArray addObject:@(minValue)];
    
}


- (int)pop {
    if (self.dataArray.count == 0) {
        NSLog(@"栈中没有元素");
        return NAN;
    }
    
    NSNumber * popNum = self.dataArray.lastObject;
    [self.dataArray removeLastObject];
    [self.minArray removeLastObject];
    return popNum.intValue;
}


- (int)min {
    if (self.minArray.count==0) {
        return NAN;
    }
    NSLog(@"当前最小值是 %@",self.minArray.lastObject);
    return self.minArray.lastObject.intValue;
}

@end

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章