每日一题算法:2020年5月30日柱状图中最大的矩形largestRectangleArea

本文探讨LeetCode题目2020年5月30日柱状图中最大的矩形面积的解题思路,包括暴力算法、双指针不适合的原因,并重点讲解如何利用栈高效求解,强调数据结构在算法中的重要性。
摘要由CSDN通过智能技术生成

2020年5月30日柱状图中最大的矩形largestRectangleArea

在这里插入图片描述

默认格式:

class Solution {

  public int largestRectangleArea(int[] heights) {
  }

}

解题思路:

这道题看起来非常难,至少他的解题思路不是非常容易就能找到的,要做出这道题要先有一个比较好的想法才可以。

方法1:暴力算法

暴力算法一直是我最喜欢的一种算法,因为能写出暴力算法至少证明了你对题目有了最基本的了解,那么使用暴力算法怎么解决呢?

第一步,获取数组的第一个元素,循环整个数组,获取这些子数组的矩形面积(最小高度X宽度)

第二步,获取数组的第二个元素…

第三步,获取数组的第三个元素…

第length步,获取数组的第length个元素…

比较上面获得的所有矩形的大小,最大的那个就是最大面积。

时间复杂度O(n^2)

我就不写这个算法了,对于算法能力提升没什么帮助。

方法2:双指针(以下说法仅代表我个人主观观点)

虽然感觉这两种方法能用,但是实际上发现这两种方法并不适合用在这里,因为滑动窗口和双指针都是单向移动的,意思就是这两种算法只能用在能够使用规律推断的,中间的部分元素对于结果不会有影响的情况,比如当时写的寻找子串的方法,在ABCDEFG中找到最小的包含CE的子串,那么在出现C之前的子串我们可以直接抛弃,在出现CE之后,又可以把下一个C之前的所有字符直接抛弃不处理。也就是说,我们只需要找到我们关注的内容就可以了,我们不关注的内容可以随意变为任意一个其他我们不关注的内容。

而在本题中,无法抛弃任何一个元素,所以没有办法使用这个算法。

方法3:

本来我自己想了一个算法,结果算到最后是错误的,有一些地方没想到。

实在没有思路了,今天就用暴力算法做出来,然后看答案再写一些理解吧。
在这里插入图片描述

int res=0;
//外层循环,每个元素进行一次
for (int i=0;i<heights.length;i++){
    int min=heights[i];
    for (int j=i;j<heights.length;j++){
        min=Math.min(min,heights[j]);
        res=Math.max(res,min*(j-i+1));
    }
}
return res;

暴力算法写起来是简单,而且还可以进行一些优化,不过没啥意义,看一看别人是怎么写的。

其实没有什么特殊的,我看完之后还是觉得挺简单的,是最基础的直接使用数据结构来节省时间的方式,但是我还是没能在第一时间想出使用栈来实现。

算法的最基本的内容,找到合适的数据结构,使我们每次计算都能为后面的计算提供帮助,这样就可以节省时间。

class Solution {
    public int largestRectangleArea(int[] heights) {
        int n = heights.length;
        int[] left = new int[n];
        int[] right = new int[n];
        
        Stack<Integer> mono_stack = new Stack<Integer>();
        for (int i = 0; i < n; ++i) {
            while (!mono_stack.isEmpty() && heights[mono_stack.peek()] >= heights[i]) {
                mono_stack.pop();
            }
            left[i] = (mono_stack.isEmpty() ? -1 : mono_stack.peek());
            mono_stack.push(i);
        }

        mono_stack.clear();
        for (int i = n - 1; i >= 0; --i) {
            while (!mono_stack.isEmpty() && heights[mono_stack.peek()] >= heights[i]) {
                mono_stack.pop();
            }
            right[i] = (mono_stack.isEmpty() ? n : mono_stack.peek());
            mono_stack.push(i);
        }
        
        int ans = 0;
        for (int i = 0; i < n; ++i) {
            ans = Math.max(ans, (right[i] - left[i] - 1) * heights[i]);
        }
        return ans;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值