第八周作业(周一)

Leetcode Array

林老师让我们在 Leetcode 找一道标签为 Array 的题目,用 Python 写。我随便找了一个 Hard 的来看看。

我找了题目 #84 ,题目链接 https://leetcode.com/problems/largest-rectangle-in-histogram/description/

题意是说,给定 a1,a2,an a 1 , a 2 , ⋯ a n ,求 max1ijn(min{ai,ai+1,,aj}(ji+1)) m a x 1 ≤ i ≤ j ≤ n ( m i n { a i , a i + 1 , ⋯ , a j } ∗ ( j − i + 1 ) )

它没写数据范围,我就枚举 i,j i , j ,敲了个 O(n2) O ( n 2 ) 的暴力交上去了……

class Solution:
    def largestRectangleArea(self, heights):
        ans = 0
        for i in range(0, len(heights)):
            p = 10000000000000
            for j in range(i, len(heights)):
                if heights[j] < p:
                    p = heights[j]
                if p * (j - i + 1) > ans:
                    ans = p * (j - i + 1)
        return ans

果然TLE了……

好吧,我想想怎么优化一下……

想到啦!线段树!把 heights 从大到小排序,然后把该 heights 对应的点的编号插入到线段树中,然后求最大连续区间!复杂度可是 O(nlogn) O ( n log ⁡ n ) 的呢!

class Solution:
    def __init__(self):
        self.h = []
        self.lmx = []
        self.rmx = []
        self.mx = []
    def add(self, p, left, right, x):
        if left == right:
            self.lmx[p] = 1
            self.rmx[p] = 1
            self.mx[p] = 1
            return
        mid = int((left + right) / 2)
        if x <= mid:
            self.add(p * 2, left, mid, x)
        else:
            self.add(p * 2 + 1, mid + 1, right, x)
        self.lmx[p] = self.lmx[p * 2]
        if self.lmx[p] == mid - left + 1:
            self.lmx[p] += self.lmx[p * 2 + 1]
        self.rmx[p] = self.rmx[p * 2 + 1]
        if self.rmx[p] == right - mid:
            self.rmx[p] += self.rmx[p * 2]
        self.mx[p] = max(self.mx[p * 2], self.mx[p * 2 + 1])
        self.mx[p] = max(self.mx[p], self.rmx[p * 2] + self.lmx[p * 2 + 1])
    def largestRectangleArea(self, heights):
        for i in range(0, len(heights)):
            self.h.append((i, heights[i]))
        self.h = sorted(self.h, key=lambda x:x[1])
        self.h.reverse()
        for i in range(0, 4 * len(self.h)):
            self.lmx.append(0)
            self.rmx.append(0)
            self.mx.append(0)
        ans = 0
        for i in range(0, len(self.h)):
            self.add(1, 0, len(self.h) - 1, self.h[i][0])
            if self.mx[1] * self.h[i][1] > ans:
                ans = self.mx[1] * self.h[i][1]
        return ans

码码码,然后交上去了……一开始mid = int((left + right) / 2) 我写成了mid = (left + right) / 2 ,然后变成实数除法(手动再见)。

改了这个bug再交,AC啦。诶诶诶怎么我跑了1324ms啊,别人平均都是50ms……

原来还有 O(n) O ( n ) 的做法啊……用单调栈维护,只需扫一遍就能出答案……垃圾Leetcode不给数据范围

贴一份别人的 O(n) O ( n ) 的代码(Python 2.7):

def largestRectangleArea(self, height):
    height.append(0)
    stack = [-1]
    ans = 0
    for i in xrange(len(height)):
        while height[i] < height[stack[-1]]:
            h = height[stack.pop()]
            w = i - stack[-1] - 1
            ans = max(ans, h * w)
        stack.append(i)
    height.pop()
    return ans
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值