【完虐算法系列】「字符串 – 滑动窗口」复盘总结 (4)

【完虐算法系列】「字符串 – 滑动窗口」复盘总结

② 元素 -3 入队;窗口范围 [0, 1]

比队尾元素 12 小,直接入队;

未形成窗口,不取值;

【完虐算法系列】「字符串 – 滑动窗口」复盘总结

③ 元素 1 入队;窗口范围 [0, 2]

比队尾元素 -3 大,所以,队尾元素出队,元素 1 入队。而且队首元素12 下标0在窗口内

取队首元素 12;

【完虐算法系列】「字符串 – 滑动窗口」复盘总结

④ 元素 -1 入队;窗口范围 [1, 3]

比队尾元素 1 小,元素 -1 入队。队首元素12 下标 0 不在窗口内,元素 12 出队;取队首元素 1 的下标 2 在窗口内;

取队首元素 1;

【完虐算法系列】「字符串 – 滑动窗口」复盘总结

⑤ 元素 9 入队;窗口范围 [2, 4]

比队尾元素 -1 和 1 都大,所以,比他小的队尾元素均出队,元素 9 入队。而且队首元素 9 下标4在窗口内

取队首元素 9;

【完虐算法系列】「字符串 – 滑动窗口」复盘总结

⑤ 元素 5 入队;窗口范围 [3, 5]

比队尾元素 9 小,元素 5 入队。而且队首元素 9 下标4在窗口内

取队首元素 9;

【完虐算法系列】「字符串 – 滑动窗口」复盘总结

利用双向队列的方式也将窗口内最大元素取出来了!

上面是整体的思路,具体到代码中,是把进入队列的元素替换为元素的下标,这样实现起来更加容易!

看下 Python 代码的实现:

class Solution(object): def maxSlidingWindow1(self, nums, k): size = len(nums) queue = collections.deque() res = [] for i in range(0, size): # 新元素进队,在队不空的情况下,需要判断与队尾元素的大小 while queue and nums[i] > nums[queue[-1]]: queue.pop() queue.append(i) # 在已经形成窗口(i+1>=k)的前提下,判断队首是否在窗口内 while queue[0] < i-k+1: queue.popleft() # 从形成窗口的时刻开始将元素置于结果集 res 中 if i+1 >= k: res.append(nums[queue[0]]) return res

无论是利用优先队列还是双向队列,都需要注意所取的元素是否在当前的窗口内。

3.无重复字符的最长子串【中等】

给定一个字符串 s ,请你找出其中不含有重复字符的 最长子串 的长度。

输入: s = "abcabcbb" 输出: 3 解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。

想要判断字符是否存在,通常会使用到字典结构来判断是否存在。

首先,初始化窗口左右端 left=0 和 right=0,初始化字典 words 用来存放已加入字符的元素(key)和元素下标(value),例如,words={'a':0,'b':1,'c':2}

然后,right 指针向右移动,判断新加入元素是否存在于字典中,如果存在,让窗口左边界指向字典对应 value 值的下一个位置,并且更新字典中对应元素的下标值(value);如果不存在,则加入字典 words 中;

注意点:

中间有可能 left 已经更新到后边,而新判断的元素可能在前面,会导致 left 变小,所以需要采用 max 来进行判断

举例:abba,执行到第二个 b 的时候,left=2,此时words={'a':0,'b':2}。后面再判断最后的 a 的时候,就会使得 left=0+1=1

因此,需要 left = max(words.get(v) + 1, left)

最后,每一步骤记录最长子串长度。

依旧用几个图清晰的一步一步操作:

① left=0, right=0, 加入新元素 'a',words={'a':0}, 窗口长度为1

【完虐算法系列】「字符串 – 滑动窗口」复盘总结

② left=0, right=1, 加入新元素 'b',words={'a':0, 'b':1}, 窗口长度为2

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zgddzg.html