关于数组最大矩形面积问题的刷题分析与学习经验分享| 豆包MarsCode AI刷题

37 阅读9分钟

一、题目解析

(一)思路
对于这道题,我们的目标是找出对于任意给定的 ,函数  的最大值,其中 。

一种可行的思路是暴力解法,也就是对于每个可能的  值(从  到数组长度 ),我们再去遍历数组中所有长度为  的子数组。对于每个子数组,先找出其中的最小值,然后按照公式计算出对应的  值,最后在所有计算出的  值中找出最大值。

然而,这种暴力解法的时间复杂度会比较高,达到了 ( 是数组长度,外层循环遍历  是 ,中层循环遍历数组起始位置是 ,内层循环找子数组最小值是 ,综合起来就是 ),当数组规模较大时效率很低。

更优的思路可以考虑使用单调栈来解决。我们可以先预处理出每个元素左右两边第一个比它小的元素的位置,然后通过这些信息来快速计算出以每个元素为最小高度时能构成的最大矩形面积,最后找出这些面积中的最大值。

(二)图解(假设数组为 [2, 1, 5, 6, 2, 3])
以单调栈思路为例,我们构建一个单调递增栈(栈中存储数组元素的下标)。

  • 开始遍历数组,当遇到元素  时,栈为空,直接将其下标  入栈。

  • 遇到元素 ,因为  比栈顶元素  小,此时我们知道以  为最小高度的矩形的右边界就是当前位置(下标为 ),左边界就是栈顶元素弹出后栈顶元素的下一个位置(此时栈为空,可认为左边界为 ),那么以  为最小高度的矩形面积可以计算出来。然后将  的下标  入栈。

  • 遇到元素 ,比栈顶元素  大,将其下标  入栈。

  • 依次类推,通过这样的过程,利用单调栈的特性,我们可以快速确定每个元素作为最小高度时矩形的左右边界,从而计算出相应的面积。

(三)代码详解(以 Python 为例,采用单调栈思路)

收起

python

复制

def largestRectangleArea(heights):
    n = len(heights)
    left_smaller = [-1] * n
    right_smaller = [n] * n

    stack = []

    # 从左到右遍历数组,找每个元素左边第一个比它小的元素位置
    for i in range(n):
        while stack and heights[stack[-1]] >= heights[i]:
            stack.pop()
        if stack:
            left_smaller[i] = stack[-1]
        stack.append(i)

    stack = []

    # 从右到左遍历数组,找每个元素右边第一个比它小的元素位置
    for i in range(n - 1, -1, -1):
        while stack and heights[stack[-1]] >= heights[i]:
            stack.pop()
        if stack:
            right_smaller[i] = stack[-1]
        stack.append(i)

    max_area = 0

    # 计算以每个元素为最小高度时的矩形面积,并找出最大值
    for i in range(n):
        area = (right_smaller[i] - left_smaller[i] - 1) * heights[i]
        max_area = max(max_area, area)

    return max_area

在上述代码中:

  • 首先初始化了两个数组 left_smaller 和 right_smaller,分别用于存储每个元素左边和右边第一个比它小的元素的位置。

  • 然后通过两次遍历数组(一次从左到右,一次从右到左),利用单调栈来更新 left_smaller 和 right_smaller 数组的值。

  • 最后,再次遍历数组,根据已经得到的左右边界信息,计算出以每个元素为最小高度时的矩形面积,并不断更新 max_area,最终返回 max_area 的值,也就是所求的最大矩形面积。

二、知识总结

(一)新知识点梳理

  1. 单调栈:这是一种特殊的数据结构,在本题中用于高效地找出每个元素左右两边第一个比它小的元素的位置。它的基本原理是通过维护一个栈内元素单调递增(或递减)的栈,在遍历数组过程中,根据当前元素与栈顶元素的大小关系,进行入栈、出栈操作,从而快速获取所需信息。

  2. 数组边界处理:在计算以每个元素为最小高度的矩形面积时,需要准确处理元素的左右边界情况。比如当一个元素左边没有比它小的元素时,我们需要合理设定其左边界(如本题中可设为 -1);同理,当右边没有比它小的元素时,要设定好右边界(如本题设为数组长度)。

(二)个人理解
单调栈这个知识点非常巧妙,它将原本需要多次遍历或者复杂比较才能得到的信息(每个元素左右两边第一个比它小的元素位置),通过巧妙地利用栈的特性,在相对线性的时间复杂度内就可以完成计算。这不仅提高了算法的效率,也让代码的逻辑更加清晰和简洁。对于数组边界处理,它是保证算法正确性的关键,只有准确地设定好每个元素的边界,才能正确计算出以该元素为最小高度的矩形面积。

(三)对入门同学的学习建议

  1. 对于单调栈,首先要理解其基本概念和原理,通过简单的示例(比如一个只有几个元素的数组)来手动模拟单调栈的入栈、出栈过程,观察它是如何获取到我们想要的信息的。然后再尝试自己去实现一个简单的单调栈应用,比如本题这样找左右边界的问题,或者其他类似的通过单调栈来优化的问题。

  2. 在学习数组边界处理时,要多思考各种边界情况,不要只局限于常规的情况。可以通过画图、列举不同的数组示例等方式,来清晰地看到每个元素在不同边界情况下应该如何设定其边界值,这样在实际编写代码时才能准确无误。

三、学习计划

(一)制定刷题计划

  1. 基础阶段:先从简单的数组相关练习题入手,比如数组的遍历、查找特定元素等基础操作的题目。熟悉编程语言中数组的基本操作和语法,这个阶段可以每天安排 2 - 3 道简单题目,花 1 - 2 个小时来完成刷题和总结。

  2. 进阶阶段:开始接触一些涉及到数组处理技巧的题目,比如本题这样利用单调栈来解决的问题。在这个阶段,每周可以安排 3 - 4 道中等难度的题目,每道题花费 2 - 3 个小时,包括理解题目、尝试自己的思路、参考别人的解法、总结知识点等环节。

  3. 巩固阶段:针对之前刷过的题目类型,进行错题回顾和同类型题目的拓展练习。可以每天抽出半个小时到一个小时来复习错题,分析当时做错的原因,然后再做几道类似但稍有变化的题目,巩固所学知识。每周也可以安排 1 - 2 道高难度的题目,挑战自己的思维极限,进一步提升自己的能力。

(二)利用错题进行针对性学习

  1. 当遇到错题时,首先要认真分析自己做错的原因。是因为对知识点不理解(比如本题中对单调栈的原理不理解),还是因为代码实现过程中的粗心大意(比如数组边界处理错误)。

  2. 针对不同的原因采取不同的措施。如果是知识点不理解,那就重新学习相关知识点,通过查阅资料、观看教学视频等方式,加深对该知识点的理解。如果是代码实现错误,要仔细检查自己的代码,找出错误的具体位置和原因,然后重新编写代码,确保类似的错误不再发生。

  3. 建立错题本,将错题整理下来,包括题目、自己的错误解法、正确解法、做错的原因以及总结的知识点等内容。定期回顾错题本,这样可以不断强化对易错知识点和易错点的记忆,提高解题的准确率。

四、工具运用

(一)结合 AI 刷题功能与其他学习资源

  1. 与在线课程相结合:在使用 AI 刷题功能的同时,可以配合相关的在线课程学习。比如在学习本题涉及到的单调栈知识点时,可以先在在线课程中系统地学习单调栈的概念、原理和应用场景,然后再通过 AI 刷题功能来做相关的练习题,检验自己的学习成果。这样可以让学习更加有系统性,先理论后实践,提高学习效率。

  2. 与编程书籍相结合:很多编程书籍都有详细的算法讲解和示例代码。在刷本题这样的题目时,可以先参考编程书籍中关于数组处理、单调栈等方面的内容,获取更多的思路和方法。然后再利用 AI 刷题功能进行针对性的练习,将书中所学的知识运用到实际解题中,加深对知识的理解和掌握。

  3. 与学习社区相结合:参与学习社区(如论坛、知乎等),在遇到问题时可以在社区里提问,获取其他同学或专家的建议和解答。比如在刷本题过程中,如果对某个知识点(如单调栈的某个细节操作)不太理解,可以在社区里发布问题,看看别人是如何理解和处理的。同时,也可以在社区里分享自己的学习经验和心得,与其他同学互相交流、互相学习,共同进步。

(二)实用的学习建议

  1. 合理安排时间:在利用多种学习资源学习时,要合理安排时间,不要只专注于某一种资源而忽略了其他。比如不能只在 AI 刷题功能上花费大量时间,而不去看在线课程或者阅读编程书籍。要根据自己的学习进度和需求,分配好不同资源的使用时间。

  2. 多做总结:无论是在使用 AI 刷题功能、学习在线课程还是阅读编程书籍,每完成一部分学习内容,都要及时进行总结。总结知识点、解题思路、代码实现等方面的内容,这样可以将所学的知识系统化,便于记忆和运用。

  3. 主动交流:积极参与学习社区的交流活动,主动提出问题,分享自己的学习经验。通过与他人的交流,可以获取更多的思路和方法,也可以发现自己学习中的不足,从而有针对性地进行改进。

希望以上内容对其他同学在学习数组相关知识以及利用 AI 刷题功能等方面能有所帮助,让大家都能在软件学习的道路上不断进步。