Leetcode刷题笔记-Sliding window

2444. Count Subarrays With Fixed Bounds

class Solution:
    def countSubarrays(self, nums: List[int], minK: int, maxK: int) -> int:
        '''
        https://leetcode.com/problems/count-subarrays-with-fixed-bounds/solutions/2708099/java-c-python-sliding-window-with-explanation/
        We maintain a maximum sliding window
        with alll elements in range [minK, maxK],
        For all A[i] as rightmost element of the subarray,
        we find the three indices j, where:
        jbad is index of last seen A[jbad] < minK || A[jbad] > maxK
        jmin is index of last seen A[jmin] = mink
        jmax is index of last seen A[jmax] = maxk

        Itearte the A[i],
        if A[i] < minK || A[i] > maxK, update jbad = i.
        if A[i] == minK, update jmin = i.
        if A[i] == maxK, update jmax = i.

        In the end of each iteration,
        the subarray ends at A[i]
        the starting element of the subarray,
        can be choosen in interval [jbad + 1, min(jmin, jmax)]
        There are min(jmin, jmax) - jbad choices,
        so we update res += max(0, min(jmin, jmax) - jbad).
        '''
        jbad = jmin = jmax = -1
        re = 0
        for i, a in enumerate(nums):
            if not minK <= a <= maxK:
                jbad = i
            if a == minK:
                jmin = i
            if a == maxK:
                jmax= i
            
            re += max(0, min(jmin, jmax) - jbad)
        return re

2134. Minimum Swaps to Group All 1's Together II

class Solution:
    def minSwaps(self, nums: List[int]) -> int:
        # sliding window, count # of 1 say x, then check x window size and see how many swaps need
        c = sum(nums)
        nums += nums
        s = sum(nums[:c]) # first window sum
        re = c - s
        for i in range(1, len(nums) - c):
            s = s + nums[i+c-1] - nums[i-1]   # add right, remove left
            re = min(re, c - s)
        return re

930. Binary Subarrays With Sum

class Solution:
    def numSubarraysWithSum(self, nums: List[int], S: int) -> int:

        def atMost(S):  # number of subarrays add up to at most S
            print("ssss", S)
            if S < 0: return 0
            res = i = 0
            for j in range(len(nums)):
                S -= nums[j]
                while S < 0:
                    S += nums[i]
                    i += 1
                res += j - i + 1  # 这个lenght 里面的 end with j 的subarry 有几个
                # print("i,j", i, j, "".join(map(str, nums))[i:j+1])
                # print("res", res)
            return res
        return atMost(S) - atMost(S - 1)

        '''
        c = collections.Counter({0: 1})
        psum = res = 0
        for i in nums:
            # print("----")
            # print("i", i)
            psum += i
            # print("presum", psum)
            # print("presum-S", psum-S)
            res += c[psum - S]  # ex1  找后面的 0101,相当于找前面的1
            # print("res", res)
            c[psum] += 1
        return res
'''

1248. Count Number of Nice Subarrays

class Solution:
    def numberOfSubarrays(self, nums: List[int], k: int) -> int:
        re = count = i = 0
        idx = []  # index of the odd numbers
        for j, v in enumerate(nums):
            if v & 1:
                count += 1
                idx.append(j)
            
            while count > k:
                if nums[i] & 1:
                    count -= 1
                    idx.pop(0)
                i += 1
            
            if count == k:
                re += idx[0] - i + 1

        return re



            
        i = count = res = 0
        for j in xrange(len(A)):
            if A[j] & 1:
                k -= 1
                count = 0
            while k == 0:
                k += A[i] & 1
                i += 1
                count += 1  # 类似于上面的解法 count [idx[0]-i+1] 但是 这个是 k==0的时候, 满足情况的时候,就开始count
            res += count
        return res

1358. Number of Substrings Containing All Three Characters

class Solution:
    def numberOfSubstrings(self, s: str) -> int:
        count = {c:0 for c in "abc"}
        res = i = 0
        for j, c in enumerate(s):
            count[c] += 1
            while all(count.values()):
                count[s[i]] -= 1
                i += 1
            res += i
        return res
        '''
        Time O(N) Space O(1)
        res += i
        This is the best line ever
        0 1 2 3 4 5 6 7 8 9
        a a a b b c c a b c
        when all a, b, c > 0 for first time at j = 5 the n after while loop i will be at i = 3, we will add 3 to result because there would be three substrings from three a's.
        Then a,b,c > 0 at j = 7 ,then we will move i until i = 5 then we will add 5 to result because there could be 5 substrings starting from 0 to second b.
        And similarly we proceed....
        '''

        '''
        和上面的解法思路一样, 只不过用last 来存 3个char的位置, 1+min(last)=0 的话代表还有char没找到
        res, last = 0, [-1] * 3
        for i, c in enumerate(s):
            last[ord(c) - 97] = i
            res += 1 + min(last)
        return res
        '''

1838. Frequency of the Most Frequent Element

class Solution:
    def maxFrequency(self, A: List[int], k: int) -> int:
        '''
        https://leetcode.com/problems/frequency-of-the-most-frequent-element/solutions/1175090/java-c-python-sliding-window/
        Sort the input array A
        Sliding window prolem actually,
        the key is to find out the valid condition:
        k + sum >= size * max
        which is
        k + sum >= (j - i + 1) * A[j]
        '''
        i = 0
        A.sort()
        s = k
        for j in range(len(A)):
            s += A[j]
            if s < (j - i + 1) * A[j]:
                s -= A[i]
                i += 1
        return j - i + 1

424. Longest Repeating Character Replacement

class Solution:
    def characterReplacement(self, s: str, k: int) -> int:
        # 2 pointers,   总长度 - 出现最多的字母的频率 要小于等于K 否则就要移动left pointer
        '''
The reason behind why it is fine to not update mostFreqLetter:
consider aaaabccc and k = 1

1st max we find is 5 (aaaab). mostFreqLetter is 4 (a). However once c rolls over in the window mostFreqLetter is no longer 4. But it doesn't matter because you can't find another substring (bccc) that is longer than the current longest substring (aaaab). However, if hypothetically the input string were aaaabccccc, then mostFreqLetter would become 5 (c in bccccc) and max would be updated to 6.
        '''
        l = 0
        count = collections.defaultdict(int)
        maxFreq = 0
        re = 0
        for r in range(len(s)):
            c = s[r]
            count[c] += 1
            maxFreq = max(maxFreq, count[c])
            print(r, l, maxFreq, k, c, r - l + 1 - maxFreq > k)
            if r - l + 1 - maxFreq > k:
                count[s[l]] -= 1
                l += 1
            re = max(re, r-l+1)
            print(re)
        return re

1658. Minimum Operations to Reduce X to Zero

class Solution:
    def minOperations(self, nums: List[int], x: int) -> int:
        # 方法1 preSum, suffic Sum 然后按照two sum的做法 但是要至少3 或者2个pass 已经O(n) space
        
        # 方法2 先求整个的sum, 左右指针都是0, 然后右指针像右移动, sum- 左边的数字, 如果sum 小于x, 左指针再像右移动 O(1) space
        n = len(nums)
        s = sum(nums)
        if s == x: return n
        l = 0
        re = n
        for r in range(n):
            s -= nums[r]
            
            while s < x and l < r:
                s += nums[l]
                l += 1
                
            if s == x:
                re = min(re, n - (r - l + 1))
                
        return re if re < n else -1

1493. Longest Subarray of 1's After Deleting One Element

class Solution:
    def longestSubarray(self, nums: List[int]) -> int:
        # sliding window
        # i, j 代表 windown的 left, right boundary 
        # sum window, 因为都是1, 最大的sum 就是i-j+1。 如果有一个是0, sum就是i-j。 如果超过1个0, sum < i-j 则需要不断pop left元素
        
        i = 0
        re = _sum = 0
        for j, n in enumerate(nums):
            _sum += n
            while _sum < j - i:
                _sum -= nums[i]
                i += 1
            re = max(re, _sum)
        return re - 1  if len(nums) == re else re
        
        '''
        # 不是sliding 的解法
        count_pre = count_cur = 0  # count previous ones and count current ones for each zeros # O(n), O(1)
        # e.x. 1 1 0 0 1 1 1 0 1 1
        re = 0
        for n in nums:
            if n == 1:
                count_cur += 1
            else:
                re = max(re, count_cur + count_pre)
                count_pre = count_cur
                count_cur = 0
                
        re = max(re, count_cur + count_pre)
        return re - 1  if len(nums) == re else re
        '''

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值