剑指offer——包含min的子结构题解

20 篇文章 2 订阅

剑指 Offer 30. 包含min函数的栈

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

示例:

MinStack minStack = new MinStack();
minStack.push(-2);
minStack.push(0);
minStack.push(-3);
minStack.min();   --> 返回 -3.
minStack.pop();
minStack.top();      --> 返回 0.
minStack.min();   --> 返回 -2.

这道题无非比正常的栈多了一个返回栈中元素最小值的接口,一开始可能会觉得直接用一个min变量一直存着最小值不就行了吗,但是万一最小值在栈顶,然后被pop掉了呢?所以这种方法是行不通的

思路分析:

我们可以开辟一个辅助栈,里面从栈底到栈顶按照降序排列数据,如果入栈的元素小于辅助栈栈顶的元素,就将其同时放入原栈与辅助栈的栈顶,当然一开始栈为空时也是同时压栈;如果需要入栈的元素大于辅助栈栈顶的元素,就将原辅助栈栈顶的元素拷贝一份放入辅助栈栈顶

我们这么做的目的是让原栈和辅助栈可以一起pop,共用一个top及capacity

当出栈的元素是最小的元素时,刚好辅助栈栈顶的元素也是最小的元素;如果出栈的元素不是最小元素,则辅助栈栈顶已经拷贝了一份最小元素,同时与原栈一起出栈,辅助栈的栈顶还是最小元素,这样就方便了许多

如下图所示:以3->1->2的入栈顺序为例

3入栈时,为当前栈最小值,所以辅助栈也放入3;1入栈时,为当前栈最小值,所以1也被放入辅助栈;2入栈时,不是当前栈最小值,所以辅助栈复制一个1放入栈顶,以保证原栈和辅助栈能够同时完成出栈

min栈动图

代码:

typedef struct {
    int capacity;
    int top;
    int* a;
    int*min;
} MinStack;

/** initialize your data structure here. */

MinStack* minStackCreate() {
    MinStack* tmp = (MinStack*)malloc(sizeof(MinStack));
    tmp->capacity = 4;
    tmp->top = 0;
    tmp->a = (int*)malloc(sizeof(int) * tmp->capacity);
    tmp->min = (int*)malloc(sizeof(int) * tmp->capacity);
    return tmp;
}

void minStackPush(MinStack* obj, int x) {
    if (obj->top == obj->capacity)//判断两栈是否需要扩容
    {
        int*tmp1 = (int*)realloc(obj->a, 2*obj->capacity*sizeof(int));
        int*tmp2 = (int*)realloc(obj->min, 2*obj->capacity*sizeof(int));
        if (tmp1 == NULL || tmp2 == NULL)
        {
            perror("realloc");
            minStackFree(obj);
        }
        else
        {
            obj->a = tmp1;
            obj->min = tmp2;
            tmp1 = NULL;
            tmp2 = NULL;
            obj->capacity *= 2;
        }
    }


    if (obj->top == 0 || obj->min[obj->top - 1] >= x)//如果x小于或等于辅助栈的栈顶元素,就将x入辅助栈
    {
        obj->min[obj->top] = x;
    }
    else//否则,将原来辅助栈栈顶的元素再复制一遍放入栈顶
    {
        obj->min[obj->top] = obj->min[obj->top - 1];
    }
        
        obj->a[obj->top] = x;//将x放入原栈顶
        obj->top++;
}

void minStackPop(MinStack* obj) {
    if (obj->top == 0)//判断栈是否为空
    return;

    obj->top--;

}

int minStackTop(MinStack* obj) {
    if (obj->top == 0)//判断栈是否为空
    return;

    return obj->a[obj->top - 1];
}

int minStackMin(MinStack* obj) {
    if (obj->top == 0)
    return;

    return obj->min[obj->top - 1];
}

void minStackFree(MinStack* obj) {
    free(obj->a);
    free(obj->min);
    obj->capacity = obj->top = 0;
    free(obj);
}
  • 7
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

WoLannnnn

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值