《算法分析与设计》Week 18

本文介绍了一种特殊栈的设计——MinStack,它除了具备普通栈的功能外,还提供了一个getMin()函数,用于获取栈中当前的最小值,并且能在常数时间内完成此操作。通过维护一个辅助栈的方式,确保了在进行push、pop等操作的同时,getMin()函数的时间复杂度保持为O(1)。

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

155. Min Stack



Description:

Design a stack that supports push, pop, top, and retrieving the minimum element in constant time.

  • push(x) -- Push element x onto stack.
  • pop() -- Removes the element on top of the stack.
  • top() -- Get the top element.
  • getMin() -- Retrieve the minimum element in the stack.

Example:

MinStack minStack = new MinStack();
minStack.push(-2);
minStack.push(0);
minStack.push(-3);
minStack.getMin();   --> Returns -3.
minStack.pop();
minStack.top();      --> Returns 0.
minStack.getMin();   --> Returns -2.


Solution:

一、题意理解

     实现一个栈,在保留原有功能的基础上,增加一个getMin()函数,获取当前栈的最小值。


二、分析

     1、当然,既然是一个算法题,getMin()函数的时间复杂度应该为O(1),而不是每一次geMin()的时候都将栈中的所有数据都pop()出来,找到最小值,再push回去。

      2、那既然这样,我们是否可以设置一个成员变量cur_min来存储当前的最小值,一旦有新的值push进来,就跟cur_min比较,更新最小值。可使这样的话,如果只有push操作是没问题的,但如果有pop操作,将最小值给pop出去了,我们如何知道第二小的这个值,将它赋值给cur_min呢?

      3、所以问题就变成了如何在将最小值pop出去的情况下,能知道第二小的值。一种方法是再开一个数组,做排序记录,将栈中的元素在这个数组中方做排序,这样就能知道每一次的最小值,但这样显然增加了很多的成本,而且有一些不必要的记录。另一种方法是我们可以在push的时候就做点文章,一旦有更小的值push进来,我们就先将cur_min入栈,以记录这个“第二小”值,再将新的“最小值”入栈。出栈的时候如果发现最小值出栈了,就再pop一次,即刻获取下一个最小值。额外空间的开销都是对我们有用的最小值。

      4、代码如下:

class MinStack {
    int min;
    stack<int> s;
public:
    /** initialize your data structure here. */
    MinStack():min(INT_MAX){
        
    }
    
    void push(int x) {
        if(x <= min)
        {
            s.push(min);
            min = x;
        }
        s.push(x);
    }
    
    void pop() {
        int top = s.top();
        s.pop();
        if(top == min) 
        {
            min = s.top();
            s.pop();
        }
    }
    
    int top() {
        return s.top();
    }
    
    int getMin() {
        return min;
    }
};

/**
 * Your MinStack object will be instantiated and called as such:
 * MinStack obj = new MinStack();
 * obj.push(x);
 * obj.pop();
 * int param_3 = obj.top();
 * int param_4 = obj.getMin();
 */





### 关于山东大学程序设计 Week5 的课程资料作业 尽管当前提供的引用并未直接提及山东大学程序设计思维实践的第5周具体内容,但从已有参考资料来看,可以推测该课程可能涉及的内容范围以及学习目标。 通常情况下,在类似的程序设计课程中,第五周的学习重点可能围绕以下几个方面展开: #### 可能的主题方向 1. **动态规划基础** 动态规划是一种解决多阶段决策过程最优化问题的方法。它通过将复杂问题分解成更简单的子问题来求解最优解[^2]。如果 Week5 涉及此主题,学生可能会接触到经典的动态规划问题,例如背包问题、最长公共子序列(LCS)、矩阵链乘法等。 2. **贪心算法的应用** 贪心算法的核心在于每一步都做出局部最优的选择,期望最终达到全局最优解。这种策略适用于某些特定场景下的问题,比如活动选择问题、霍夫曼编码等问题[^1]。 3. **图论初步** 图论作为离散数学的重要分支之一,在计算机科学中有广泛的应用价值。Week5 也可能引入基本概念如连通性检测、最小生成树(Kruskal 和 Prim 算法),或者单源最短路径(Dijkstra 算法)[^4]。 4. **高级数据结构介绍** 高级的数据结构能够显著提升解决问题效率。例如堆(Heap)用于实现优先队列;并查集(Union-Find Set)用来处理集合合并操作等等[^3]。 以下是基于上述假设整理的一道典型练习题及其解答思路: --- #### 练习题示例:最大连续子数组和 给定一个整数数组 `nums` ,找到其中具有最大和的一个连续子数组,并返回其总和。 ##### 思路分析: 采用 Kadane's Algorithm 来高效完成任务。核心思想是在遍历过程中维护两个变量——当前的最大子数组结束位置处的累加值(`current_sum`)以及迄今为止发现的整体最大值(`max_so_far`)。每当遇到新的元素时更新这两个量即可得出答案。 ```python def maxSubArray(nums): current_sum = nums[0] max_so_far = nums[0] for i in range(1, len(nums)): # 判断是否应该重新开始一个新的子数组还是延续之前的 current_sum = max(nums[i], current_sum + nums[i]) # 更新整体最大值 max_so_far = max(max_so_far, current_sum) return max_so_far ``` --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值