leetcode之滑动窗口

滑动窗口即在一个序列中维持一个窗口,这个窗口由左指针和右指针表示,使用滑动窗口可以减少大量的重复计算

2021.1.28
无重复字符的最长字串
1.使用两个指针表示字符串的某个字串。其中左指针在下面的代码中为i,右指针为rk。

2.在每一步的操作中,将左指针向右移动一格,表示开始枚举下一个字符作为起始位置,然后不断的向右移动右指针,直到遇到重复的字符,记录下字串长度。
时间复杂度: O ( n ) O(n) O(n) n n n表示字符串长度
空间复杂度: O ( e ) O(e) O(e) e e e表示字符集的大小

class Solution:
    def lengthOfLongestSubstring(self, s: str) -> int:
        # 哈希集合,记录每个字符是否出现过
        occ = set()
        n = len(s)
        # 右指针,初始值为 -1,相当于我们在字符串的左边界的左侧,还没有开始移动
        rk, ans = -1, 0
        for i in range(n):
            if i != 0:
                # 左指针向右移动一格,移除一个字符
                occ.remove(s[i - 1])
            while rk + 1 < n and s[rk + 1] not in occ:
                # 不断地移动右指针
                occ.add(s[rk + 1])
                rk += 1
            # 第 i 到 rk 个字符是一个极长的无重复字符子串
            ans = max(ans, rk - i + 1)
        return ans

2021.2.22
串联所有单词的子串
这道题我想了很久,但还是在一些例子上不通过,主要的原因的窗口的维护上不够好,先贴上我写的不通过的代码

class Solution:
    def findSubstring(self, s: str, words: List[str]) -> List[int]:
        words = sorted(words)
        length = len(words[0])
        Index = []
        tail = 0
        i=0
        for j in range(length):
            i = tail = j
            List = []
            while(i<len(s)):
                if i != 0 and s[i-length:i] in List:
                    List.remove(str(s[i-length:i]))
                while tail+length<=len(s) and s[tail:tail+length] in words and len(List) < len(words):
                    List.append(str(s[tail:tail+length]))
                    tail = tail + length

                if i == tail:
                    tail = tail+1
                if sorted(List) == words:
                    Index.append(i)
                    i = i + length
                    continue
                i = i+1

            
        Index = list(set(Index)) 

        return Index

对于"mississippi"[“si”,“is”]这种情况我的输出是[0],预期输出是[0,4]。

正确答案

class Solution:
    def findSubstring(self, s: str, words: List[str]) -> List[int]:
        if not s or not words:
            return []
        n = len(s)
        one_word_len = len(words[0])        #一个单词的长度
        word_cnt = len(words)               #单词的个数
        all_len = one_word_len * word_cnt

        words_cnt = defaultdict(int)        #每个单词出现的次数
        for w in words:
            words_cnt[w] += 1

        res = [] 
        for i in range(one_word_len):       #shell希尔排序的套路 start  delta = 一个单词的长度
            cur_w_num = 0                     #单词个数
            L, R = i, i
            cur_w_dic = defaultdict(int)      #当前单词的次数统计
            while R + one_word_len <= len(s):
                w = s[R: R + one_word_len]
                R += one_word_len           #R每次像右移一个单词的长度 类似于shell排序中的delta

                if w not in words_cnt:          #结束前,出现个不知道哪里的单词,整个前面一片就废了
                    L = R
                    cur_w_dic.clear()
                    cur_w_num = 0
                else:
                    cur_w_dic[w] += 1
                    cur_w_num += 1
                    while cur_w_dic[w] > words_cnt[w]:
                        L_w = s[L : L + one_word_len]
                        L += one_word_len       #L右移
                        cur_w_dic[L_w] -= 1       #做好统计
                        cur_w_num -= 1
                    if cur_w_num == word_cnt:     #如果说ok了
                        res.append(L)
        
        return res

2021.2.24
1052.爱生气的书店老板
开心,这是第一道没有看答案独立完成的中等难度题目
思路很简单,把不生气时的顾客数全部加起来,然后通过滑动窗口计算窗口中生气时的顾客数的最大值。把不生气时的顾客总数加上生气时的最大值就是答案。

class Solution:
    def maxSatisfied(self, customers: List[int], grumpy: List[int], X: int) -> int:

        tail=0
        ALL=0
        MAX=0
        cur=0
        length = len(customers)
        for i in range(length):
            while tail-i<X and tail+1<=length:
                if grumpy[tail]==1:
                    cur += customers[tail]
                    MAX = max(cur,MAX)
                else:
                    ALL += customers[tail]
                tail += 1
            if grumpy[i]==1:
                cur -= customers[i]
        return ALL + MAX
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值