LeetCode个人笔记python篇(hard)

本文介绍了如何使用Python解决LeetCode中的84和85题,通过引入单调栈优化算法,将时间复杂度降低到O(n)。针对每个柱形图,利用单调栈找出左右边界,从而计算最大矩形面积。同时,该方法也适用于85题,通过辅助数组处理特殊情况。此外,还讨论了154题,这是153题的扩展,需要处理重复数字并正确处理各种等号情况。
摘要由CSDN通过智能技术生成

84. 柱状图中最大的矩形

        拿到这个问题很容易想到,对于每一个柱形图,只要向左向右去遍历,然后找到左边第一个小于他的点和右边第一个小于他的点,就可以得到宽度,然后再乘上它的高,就可以得到当前的矩形面积。从左到右依次遍历并且更新结果,最后就可以求得最大的矩形面积。

        容易得到,这个解法的时间复杂度为O(n^2),那么怎么优化呢,首先要考虑,从左到右的遍历是免不了的,那么对于每一个点,求解它左右的第一个小于它的元素,这个点是不是可以优化呢。所以这里就用到了单调栈,我们可以花费一点空间,用一个栈来维护一组下标,对于栈中的每一个下标所对应的元素,它的左边第一个比他小的元素的下标就是栈中的前一个下标,有了这样的思路,就容易解决问题了。

class Solution(object):
    def largestRectangleArea(self, heights):
        """
        :type heights: List[int]
        :rtype: int
        """
        stack = []
        maxarea = 0
        for i in range(len(heights)):
            while stack and heights[i] <= heights[stack[-1]]:
                peek = stack.pop()
                maxleft = stack[-1] if stack else -1
                curArea = (i - maxleft -1)*heights[peek]
                maxarea = max(curArea,maxarea)
            stack.append(i)
        while stack:
            peek = stack.pop()
            maxleft = stack[-1] if stack else -1
            curArea = (len(heights) - maxleft -1)*heights[peek]
            maxarea = max(curArea,maxarea)
        return maxarea

85. 最大矩形

此题和84题一样的解法,同样是用单调栈,先给出一个辅助数组,记录是否遇到0,不是就加一,是就变0.

class Solution(object):
    def maximalRectangle(self, matrix):
        """
        :type matrix: List[List[str]]
        :rtype: int
        """
        if not matrix: return 0

        maxarea = 0
        dp = [0] * len(matrix[0])
        for i in range(len(matrix)):
            for j in range(len(matrix[0])):

                # update the state of this row's histogram using the last row's histogram
                # by keeping track of the number of consecutive ones

                dp[j] = dp[j] + 1 if matrix[i][j] == '1' else 0

            # update maxarea with the maximum area from this row's histogram
            maxarea = max(maxarea, self.maxRect(dp))
        return maxarea
    def maxRect(self, heights):
        stack = []
        maxarea = 0
        for i in range(len(heights)):
            while stack and heights[i] <= heights[stack[-1]]:
                peek = stack.pop()
                maxleft = stack[-1] if stack else -1
                curArea = (i - maxleft -1)*heights[peek]
                maxarea = max(curArea,maxarea)
            stack.append(i)
        while stack:
            peek = stack.pop()
            maxleft = stack[-1] if stack else -1
            curArea = (len(heights) - maxleft -1)*heights[peek]
            maxarea = max(curArea,maxarea)
        return maxarea

154. 寻找旋转排序数组中的最小值 II

这题是153的延伸,区别就是允许重复数字的出现。因此增加了一个当first = mid = last时,按顺序查找最小值。(此题特别注意是各种等号要加进去,不然就会判断错误)

class Solution(object):
    def findMin(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        first = 0
        last = len(nums) - 1
        flag = 0
        while nums[first] >= nums[last]:
            flag = 1
            if last - first == 1:
                mid = last
                break
            mid = (first + last)//2
            if nums[first] == nums[mid] and nums[mid] == nums[last]:
                return self.inorderNum(nums,first,last)
            if nums[mid] >= nums[first]:
                first = mid
            elif nums[mid] <= nums[first]:
                last = mid
        print(flag)
        if flag == 0:
            return nums[0]
        else:
            return nums[mid]
    def inorderNum(self,nums,first,last):
        result = nums[first]
        for i in range(first+1,last+1):
            if result > nums[i]:
                result = nums[i]
        return result

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值