雙周賽352。

題目

輸入整數陣列nums。
若一個子陣列滿足以下條件,則稱為連續的

  • 子陣列中任意兩個元素的絕對差 <= 2

求有多少連續的子陣列。

解法

假設有一個陣列a,最大值和最小值的差為2,則無論刪掉陣列中任何元素,必定不會使絕對差增加。
因此只需要枚舉所有索引r作為右端點,找到與其對應的最長左端點l。這時r可以和[l,r]之間的任意索引組成連續的子陣列。

使用sorted list來維護子陣列的最大、最小值。枚舉右端點r,將nums[r]加入sl,若最大值和最小值的差超過2,則不斷縮減左邊界l。
縮減結束後,子陣列的長度為l-r+1,也就是r可以和l-r+1個左端點組成連續的子陣列,更新答案。

時間複雜度O(N log N)。
空間複雜度O(N)。

from sortedcontainers import SortedList as SL

class Solution:
    def continuousSubarrays(self, nums: List[int]) -> int:
        ans=0
        sl=SL()
        
        l=0
        for r,x in enumerate(nums):
            sl.add(x)
            while sl[-1]-sl[0]>2:
                sl.remove(nums[l])
                l+=1
            ans+=r-l+1
            
        return ans

但絕對差最大只會到2,也就是說子陣列中最多只會有三種數字
這時只要用普通的雜湊表計數即可,每次查找最大最小值只要O(3),可以視作O(1)。

時間複雜度O(N)。
空間複雜度O(1)。

class Solution:
    def continuousSubarrays(self, nums: List[int]) -> int:
        ans=0
        d=Counter()
        
        l=0
        for r,x in enumerate(nums):
            d[x]+=1
            while max(d)-min(d)>2:
                d[nums[l]]-=1
                if d[nums[l]]==0:
                    del d[nums[l]]
                l+=1
            ans+=r-l+1
            
        return ans