前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Data Structures and Algorithms Basics(014):Sliding Window

Data Structures and Algorithms Basics(014):Sliding Window

作者头像
用户5473628
发布2019-08-08 15:11:10
3490
发布2019-08-08 15:11:10
举报
文章被收录于专栏:MiningAlgorithmsMiningAlgorithms

Sliding Window

目录:

1,删除重复元素

2,删除后,重复值不超过两个

3,删除元素

4,最大均值子数组

5,最长连续递增子序列

6,最短子数组之和

7,实现strStr()函数

8,子数组乘积小于K

9,不含重复字符的最长子串

10,查找重组子串

11,最小窗口子串

12,最多有K个不同字符的最长子串

13,滑动窗口最大值

代码语言:javascript
复制
# 1,删除重复元素:
def removeDuplicates(alist):
    if not alist:
        return 0

    tail = 0

    for j in range(1, len(alist)):
        if alist[j] != alist[tail]:
            tail += 1
            alist[tail] = alist[j]

    return tail + 1

def removeDuplicates(alist):
    i = 0
    for n in alist:
        if i == 0 or n > alist[i - 1]:
            alist[i] = n
            i += 1
    return i

if __name__ == '__main__':
  alist = [0,0,1,1,1,2,2,3,3,4]
  print(removeDuplicates(alist))

# 2,删除后,重复值不超过两个:
def removeDuplicates(nums):
    if len(nums) <= 2: return len(nums)
    prev, curr = 1, 2
    while curr < len(nums):
        if nums[curr] == nums[prev] and  nums[curr] == nums[prev - 1]:
            curr += 1
        else:
            prev += 1
            nums[prev] = nums[curr]
            curr += 1
    return prev + 1

def removeDuplicates2(nums):
    count = 0
    for i in range(len(nums)):
        if count < 2 or nums[count - 2] != nums[i]:
            nums[count] = nums[i]
            count += 1
    return count

# 3,删除元素:给定一个数组nums和一个值val, 就地(in-palce)删除这个val的所有实 例,并返回新的数组的长度。
def removeElement(nums, val):
    i = 0
    for j in range(len(nums)):
        if nums[j] != val:
            nums[i] = nums[j]
            i += 1
    return i        

def removeElement2(nums, val):
    start, end = 0, len(nums) - 1
    while start <= end:
        if nums[start] == val:
            nums[start], end = nums[end], end - 1
        else:
            start +=1
    return start

if __name__ == '__main__':
  nums = [ 0, 1, 2, 2, 3, 0, 4, 2 ]
  removeElement(nums, 2)

# 4,最大均值子数组: 给定一个包含n个整数的数组,找到长度为k的平均值最大的连续子数组,返回最大平均值 
def findMaxnumsverage(nums, K):
    P = [0]
    for x in nums:
        P.append(P[-1] + x)

    moving_sum = max(P[i+K] - P[i] 
             for i in range(len(nums) - K + 1))
    return moving_sum / float(K)

def findMaxnumsverage2(nums, K):
    moving_sum = 0.0
    for i in range(K):
        moving_sum += nums[i]
    res = moving_sum
    for i in range(K, len(nums)):
        moving_sum += nums[i] - nums[i - K]
        res = max(res, moving_sum)
    return res / K

if __name__ == '__main__':
  nums = [ 1, 12, -5, -6, 50, 3 ]
  findMaxnumsverage2(nums, 4)

# 5,最长连续递增子序列:给定一个没排序的整数数组,找到最长的连续递增的子序列子数组的长度
def findLengthOfLCIS(nums):
    result, count = 0, 0
    for i in range(len(nums)):
        if i == 0 or nums[i-1] < nums[i]:
            count += 1
            result = max(result, count)
        else:
            count = 1
    return result

if __name__ == '__main__':
  nums = [1,3,5,4,7]
  findLengthOfLCIS(nums)

# 6,最短子数组之和: 给定一个包含n个正整数的数组和一个正整数s,找到一个长度最小的连续子数组,这个子数组的元素和大于等于s
def minsubarray(alist, target):
    if len(alist) == 0:
        return 0
    
    i = j = sums = 0
    minimum = sys.maxsize
    
    while j < len(alist):
        sums += alist[j]
        j += 1
        while sums >= target:
            minimum = min(minimum, j - i)
            sums -= alist[i]
            i += 1
    return 0 if min == sys.maxsize else minimum

# 7,实现strStr()函数: 返回子字符串needle在字符串haystack中第一次出现的位置,没有则返回-1 
def strStr(haystack, needle):
    if len(haystack) < len(needle): 
        return None
    i = 0
    while i < len(haystack) - len(needle) + 1:
        j = 0
        k = i
        while j < len(needle):
            if haystack[k] == needle[j]:
                j+=1; k+=1
            else:
                break
        if j == len(needle):
            break
        else:
            i+=1
    if i == len(haystack)-len(needle)+1:
        return None
    else:
        return haystack[i:]

def strStr2(haystack, needle):
    if len(haystack) < len(needle): 
        return None
    l1 = len(haystack)
    l2 = len(needle)
    for i in range(l1 - l2 + 1):
        count = 0
        while count < l2 and haystack[i + count] == needle[count]:
            count += 1
        if count == l2:
            return i
    return -1

# 8,子数组乘积小于K:
def bruteforce(nums, k):
    count = 0
    for i in range(len(nums)):
        product = 1
        for j in range(i, len(nums)):
            product *= nums[j]
            if (product >= k): break
            count += 1
    return count

def numSubarrayProductLessThanK(nums, k):
    product = 1
    i = 0
    ans = 0
    for j, num in enumerate(nums):
        product *= num
        while product >= k:
            product /= nums[i]
            i += 1
        ans += (j - i + 1)
    
    return ans


if __name__ == '__main__':
  nums = [1,5,4,3,6,2,7]
  k = bruteforce(nums, 100)
  print(k)
  nums = [10, 5, 2, 6]
  k = numSubarrayProductLessThanK(nums, 100)
  print(k)

# 9,不含重复字符的最长子串: 
def lengthOfLongestSubstring(s):
    usedChar = set()
    maxLength = 0
    i = j = 0
    n = len(s)
    while (i < n and j < n):
        if s[j] not in usedChar:
            usedChar.add(s[j])
            j += 1
            maxLength = max(maxLength, j - i)
        else:
            usedChar.remove(s[i])
            i += 1
    return maxLength

def lengthOfLongestSubstring2(s):
    start = maxLength = 0
    usedChar = {}

    for i, c in enumerate(s):
        if c in usedChar and start <= usedChar[c]:
            start = usedChar[c] + 1
        else:
            maxLength = max(maxLength, i - start + 1)

        usedChar[c] = i

    return maxLength

if __name__ == '__main__':
  s = 'pwwkew'
  lengthOfLongestSubstring(s)

# 10,查找重组子串:给定一个字符串s和一个非空字符串p,找到所有p的重组字符串在s中出现的初始位置 
import collections
def findAnagrams(s, p):
    begin, end = 0, 0
    count = len(p)
    ans = []
    d = collections.Counter(p)

    while end < len(s):
        # map[char]>=1, meaning the new char is in p, then count--
        if d[s[end]] > 0:
            count -= 1
        d[s[end]] -= 1
        end += 1

        # find an anagram
        if count == 0:
            ans.append(begin)

        # find a window, then advance begin to shrink the window
        if end - begin == len(p):
            # advance begin
            d[s[begin]] += 1
            begin += 1
            # # map[char]>=1, meaning the exit char is in p, then count++
            if d[s[begin-1]] >= 1:
                count += 1

    return ans

from collections import Counter

def findAnagrams2(s, p):
    res = []
    pCounter = Counter(p)
    sCounter = Counter(s[:len(p)-1])
    for i in range(len(p)-1,len(s)):
        sCounter[s[i]] += 1   # include a new char in the window
        if sCounter == pCounter:    # This step is O(1), since there are at most 26 English letters 
            res.append(i-len(p)+1)   # append the starting index
        sCounter[s[i-len(p)+1]] -= 1   # decrease the count of oldest char in the window
        if sCounter[s[i-len(p)+1]] == 0:
            del sCounter[s[i-len(p)+1]]   # remove the count if it is 0
    return res

if __name__ == '__main__':
  s = "cbaebabacd"
  p = "abc"
  findAnagrams(s, p)

# 11,最小窗口子串:
import sys
def minWindow(s, t):
    if len(t) > len(s):
        return ""
    lt = len(t)
    count = lt
    ct = collections.Counter(t)
    left = 0
    right = 0
    minLength = sys.maxsize
    notfound = 1
    ansleft = 0
    ansright = 0
    print(ct)
    for i in range(len(s)):
        # found in t
        if ct[s[i]] > 0:
            count -= 1
        ct[s[i]] -= 1
        #print(s[i], ct)
        # found a window, containing all chars from t
        while count == 0:
            right = i
            notfound = 0
            if right - left < minLength:
                minLength = right-left
                ansleft = left
                ansright = right
            # when map[left] is 0, meaning the exit char is in t, then count++
            if ct[s[left]] == 0:
                count += 1
            ct[s[left]] += 1
            #print("left: ", s[left], ct)
            left += 1
    if notfound == 1:
        return ""
    return s[ansleft:ansright+1]

if __name__ == '__main__':
  s = "ADOBECODEBANC"
  t = "ABC"
  minWindow(s, t)

# 12,最多有K个不同字符的最长子串:
def lengthOfLongestSubstringKDistinct(s, k):
    longest, start, distinct_count, visited = 0, 0, 0, [0 for _ in range(256)]
    for i, char in enumerate(s):
        if visited[ord(char)] == 0:
            distinct_count += 1
        visited[ord(char)] += 1

        while distinct_count > k:
            visited[ord(s[start])] -= 1
            if visited[ord(s[start])] == 0:
                distinct_count -= 1
            start += 1

        longest = max(longest, i - start + 1)
    return longest

def lengthOfLongestSubstringKDistinct2(s, k):
    start = 0
    longest = 0
    char_dict = {}


    for index in range(len(s)):
        char = s[index]
        char_dict[char] = char_dict.get(char, 0) + 1  # track count of chars

        # decrease the size of sliding window until you have k unique chars in sliding window
        while len(char_dict) > k: 
            char_dict[s[start]] -= 1
            if char_dict[s[start]] == 0:
                del char_dict[s[start]]
            start += 1

        longest = max(longest, index+1-start)

    return longest

if __name__ == '__main__':
  nums = 'eceba'
  k = 2
  lengthOfLongestSubstringKDistinct(nums, k)

# 13,滑动窗口最大值:
def maxSlidingWindow(nums, k):
    d = collections.deque()
    out = []
    for i, n in enumerate(nums):
        while d and nums[d[-1]] < n:
            d.pop()
        d += i,
        if d[0] == i - k:
            d.popleft()
        if i >= k - 1:
            out += nums[d[0]],
    return out

if __name__ == '__main__':
  nums = [1,3,-1,-3,5,3,6,7]
  k = 3
  maxSlidingWindow(nums, k)
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-05-11,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 MiningAlgorithms 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档