单调栈算法(leetcode 1124 表现良好的最长时间段)

【单调栈的定义】

满足单调性的栈结构

单调栈算法(leetcode 1124 表现良好的最长时间段)_第1张图片

【图例】

单调栈算法(leetcode 1124 表现良好的最长时间段)_第2张图片

【leetcode 1124 表现良好的最长时间段】

【题目】

给你一份工作时间表 hours,上面记录着某一位员工每天的工作小时数。

我们认为当员工一天中的工作小时数大于 8 小时的时候,那么这一天就是「劳累的一天」。

所谓「表现良好的时间段」,意味在这段时间内,「劳累的天数」是严格 大于「不劳累的天数」。

请你返回「表现良好时间段」的最大长度。

 

示例 1:

输入:hours = [9,9,6,0,6,6,9]
输出:3
解释:最长的表现良好时间段是 [9,9,6]。
 

提示:

1 <= hours.length <= 10000
0 <= hours[i] <= 16

【分析】

第一步:根据时间是否大于8,将每一天的工作小时数量化成1与-1,这样有利于后续的计算。

题目中的[9,9,6,0,6,6,9]被量化为[1,1,-1,-1,-1,-1,1]。这样,理解题意,可以看出我们需要得到一个区间,在这个区间里面1和-1加起来要大于0。

第二步:怎样可以更方便的得到一个区间的和?

在这里,我们需要利用前缀和这个方法。利用前缀和方法,我们可以将[1,1,-1,-1,-1,-1,1]转化为前缀和prefixSrc = [0, 1, 2, 1, 0, -1, -2, -1],我们在前缀和前面加了一个0,是为了好操作。

如果要得到[1,3]区间的和,根据前缀和的定义,只需要使用prefixSrc[3]-prefixSrc[0]即可。

第三步:我们现在需要找到的是:区间和>0的最长区间。

那么可以这样思考,想要prefixSrc[j]大于prefixSrc[i],我们只需要找到比prefixSrc[j]更小的元素在哪里就可以了。这样就可以使用单调栈了。

我们先遍历一遍prefixSrc ,建议一个严格单调递减的单调栈,这样我们的栈顶元素就一定是prefixSrc 中的最小值。(其中,栈中存储的是元素的索引)

然后,我们从后向前遍历prefixSrc ,若遍历到的元素大于栈顶元素,则这个区间是符合规则的,需要记录下区间的大小,并且我们将栈顶元素弹出,然后继续比较当前遍历到的元素是不是大于栈顶元素。

单调栈算法(leetcode 1124 表现良好的最长时间段)_第3张图片   

                                              图一

  单调栈算法(leetcode 1124 表现良好的最长时间段)_第4张图片

                                        图二

单调栈算法(leetcode 1124 表现良好的最长时间段)_第5张图片     

                                          图三   

  单调栈算法(leetcode 1124 表现良好的最长时间段)_第6张图片

                                      图四

单调栈算法(leetcode 1124 表现良好的最长时间段)_第7张图片

                                      图五

【python代码】

class Solution:
    def longestWPI(self, hours: List[int]) -> int:
        num = [ 0 for i in range(len(hours))]
        for i in range(len(hours)):
            if hours[i] > 8:
                num[i] = 1
            else:
                num[i] = -1
        j = 0
        ans = []
        ans.append(j)
        for i in num:
            j = j + i
            ans.append(j)
        stack = []
        for i in range(len(num)):
            if len(stack) == 0 or ans[stack[-1]] > ans[i]:
                stack.append(i)
        k = 0
        n = len(hours)
        while n > k:
            while len(stack) != 0 and ans[stack[-1]] < ans[n]:
                k = max(k,n-stack[-1])
                stack.pop()
            n -= 1
        return k

 

 

 

你可能感兴趣的:(单调栈)