【leetcode】907. Sum of Subarray Minimums

题目如下:

解题思路:我的想法对于数组中任意一个元素,找出其左右两边最近的小于自己的元素。例如[1,3,2,4,5,1],元素2左边比自己小的元素是1,那么大于自己的区间就是[3],右边的区间就是[4,5]。那么对于元素2来说,和左边区间合并组成[2,3]以及和右边区间合并组成[2,4,5],这两段区间包括2在内的所有subarray的最小值都是2,其分别可以组成的subarry的个数是 len([3])和len([4,5]),左右区间合并在一起可以组成的subarray的个数是len([3])*len([4,5]),再加上2本身自己组成一个独立的subarray [2],其总数就是 len([3]) + len([4,5]) + len([3])*len([4,5]) + 1,转成通项表达式就是 len(left) + len(right) + len(left)*len(right) + 1。怎么快速找到其左右两边最近的小于自己的元素?可以参考【leetcode】84. Largest Rectangle in Histogram 。

代码如下:

class Solution(object):
    def sumSubarrayMins(self, A):
        """
        :type A: List[int]
        :rtype: int
        """
        dic = {}
        for i in range(len(A)):
            if A[i] not in dic:
                dic[A[i]] = 0
            else:
                dic[A[i]] += 1
                A[i] = float(str(A[i]) + '.' + '1'*dic[A[i]])
        dp_left = [0] * len(A)
        dp_left[0] = -1
        for i in xrange(1, len(dp_left)):
            j = i - 1
            while A[i] <= A[j] and j != -1:
                j = dp_left[j]
            dp_left[i] = j
        # print dp

        dp_right = [0] * len(A)
        dp_right[-1] = len(A)
        for i in xrange(len(dp_right) - 2, -1, -1):
            j = i + 1
            while j != len(A) and A[i] <= A[j]:
                j = dp_right[j]
            dp_right[i] = j


        res = 0
        for i in range(len(A)):
            left = i - dp_left[i] - 1
            right = dp_right[i] - i - 1
            A[i] = int(A[i])
            res += (left*A[i] + right*A[i] + (left*right)*A[i] + A[i])
                #print A[i],res
        #print dp_left
        #print dp_right
        return res % (pow(10,9) + 7)
        
原文地址:https://www.cnblogs.com/seyjs/p/9670397.html