[LeetCode] 2863. Maximum Length of Semi-Decreasing Subarrays_Medium tag: stack

发布时间 2023-10-12 05:05:20作者: Johnson_强生仔仔

You are given an integer array nums.

Return the length of the longest semi-decreasing subarray of nums, and 0 if there are no such subarrays.

  • subarray is a contiguous non-empty sequence of elements within an array.
  • A non-empty array is semi-decreasing if its first element is strictly greater than its last element.

 

Example 1:

Input: nums = [7,6,5,4,3,2,1,6,10,11]
Output: 8
Explanation: Take the subarray [7,6,5,4,3,2,1,6].
The first element is 7 and the last one is 6 so the condition is met.
Hence, the answer would be the length of the subarray or 8.
It can be shown that there aren't any subarrays with the given condition with a length greater than 8.

Example 2:

Input: nums = [57,55,50,60,61,58,63,59,64,60,63]
Output: 6
Explanation: Take the subarray [61,58,63,59,64,60].
The first element is 61 and the last one is 60 so the condition is met.
Hence, the answer would be the length of the subarray or 6.
It can be shown that there aren't any subarrays with the given condition with a length greater than 6.

Example 3:

Input: nums = [1,2,3,4]
Output: 0
Explanation: Since there are no semi-decreasing subarrays in the given array, the answer is 0.

 

Constraints:

  • 1 <= nums.length <= 105
  • -109 <= nums[i] <= 109

 

1. T: O(n * lgn)

利用排序来得到从大到小的(num, index)的list, 然后利用类似于贪心算法,traverse nums, 依次将num 和list[-1][0] 比较,如果num > lists[-1][0], ans = max(ans, lists[-1][1] - index + 1), 因为如果是符合的那从左到右traverse应该是longest subarray。

class Solution:
    def maxSubarrayLength(self, nums: List[int]) -> int: 
        highs = sorted([(num, index) for index, num in enumerate(nums)], reverse = True)
        ans = 0
        for index, num in enumerate(nums):
            while highs and num > highs[-1][0]:
                ans = max(ans, highs[-1][1] - index + 1)
                highs.pop()
        return ans

 

2. T: O(n)

这个思路关键在于理解,如果有(i, j)这样符合条件的longest subarray, 那么在i之前不会有比nums[i] 大的数,同理在j之后不会有比nums[j] 小的数,所以思路如下

1)我们先来找i, 先从左往右扫一遍nums, 建一个strict increase stack(存index), 这样能保证在每一个index 之前不会有比nums[index] 大的数

2)我们来找j, 从右往左扫一遍nums, 如果nums[i] > nums[j], 将i pop出来,然后一直到j的i已经被找到。每一次update ans = max(ans, j - i + 1)

class Solution:
    def maxSubarrayLength(self, nums: List[int]) -> int: 
        ans = 0
        stack = []
        n  = len(nums)
        # get the potential i and store it in stack
        for i, num in enumerate(nums):
            if not stack or nums[stack[-1]] < num:
                stack.append(i)
        
        # check each j and see if there are i could match the condition nums[i] > nums[j]
        for j in range(n - 1, -1, -1):
            while stack and nums[stack[-1]] > nums[j]:
                i = stack.pop()
                ans = max(ans, j - i + 1)
        return ans