在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

 

 

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