这道题主要是考察滑动窗口的应用,而滑动窗口的程序比较绕,因为边界条件实在是有点复杂,但是套路比较固定,一般在数组中考察,题干一般含有"连续子数组"等字样
参考链接:
https://zhuanlan.zhihu.com/p/61564531
框架
初始化窗口端点L,R,一般L为0,R为1
初始化最优值
while R < len(Array):
while R < len(Array):
R += 1 #移动右端点
if R < len(Array):
更新状态
if 状态满足条件:
可选的更新最优值的位置
break #一旦满足条件即跳出
if R == len(Array): # 若循环是由于移动到数组末尾结束,则停止整个程序。因为之后已经不再有可能的解
break
while L < R:
更新状态 # 移动左端点,需要更新状态
L += 1
if 状态满足条件:
可选的更新最优值的位置
else: # 一旦窗口所在区间不再满足条件即跳出,去移动右端点
break
可选的对于L,R端点的后续处理
return 最优值
依次解读:
第一层循环保证了右部标记不会超出数组,之后将右部标记移动至刚好满足条件的地方,结束while循环,为什么能够保证第一层循环不会溢出呢,因为只要R不等于数组长度,就可以保证所有的R可能性都已经遍历完了,也就代表着所有对应的左侧标记也已标记完成,即所有情况也已经完成,第二层while循环表示移动左部标记使其不满足条件,然后纪录其状态,之后循环,得到最优位置。
例题:
https://leetcode-cn.com/problems/minimum-size-subarray-sum/
代码:
class Solution:
def minSubArrayLen(self, target: int, nums: List[int]) -> int:
left,right,minvalue,sumvalue = 0,-1,float('inf'),0 #初始化,left为
while(right<len(nums)): #while循环保证
while(right<len(nums)):
right += 1 #右边逐渐移动
if(right<len(nums)):
sumvalue+=nums[right] #一直相加
if(sumvalue>=target):
minvalue = min(minvalue,right-left+1) #在两者之间比较出最小值
break
if(right==len(nums)):
break
while(left<right):
sumvalue-=nums[left]
left+=1
if(sumvalue>=target): #也就是在left+1之后还小于
minvalue = min(minvalue,right-left+1)
else: #如果还能小就退出
break
if(minvalue==float('inf')):
return 0
return minvalue
上面的代码一开始看着有点复杂,但是可以保证许多情况下都适用,
题目
https://leetcode-cn.com/problems/longest-substring-without-repeating-characters/
这道题其实没什么不同,也就是判断的情况不同了几种,判断最大值仍在right扩大的过程中寻找,因为在left移动时是不会存在最大值的,详细看代码就行
class Solution:
def lengthOfLongestSubstring(self, s: str) -> int:
left,right, = 0,-1 #将right赋值为-1的好处是第一个循环不会崩掉
list1 = [] #这里面的数组不会有重复字符
minvalue = 0
while(right<len(s)):
while(right<len(s)):
right+=1
if(right>=len(s)):
minvalue = max(minvalue,right-left)
break
if(s[right] not in list1): #
list1.append(s[right]) #如果不重复就加入数组
else: #如果在这里面了就计算最大值
minvalue = max(minvalue,right-left) #这里面写right - left的原因是right本身就不算了
break
if(right==len(s)):
break
while(left<right):
if(s[left]!=s[right]): #如果不等于的话就继续找,并移除数字
list1.remove(s[left])
left+=1
else: #找到了就将left向右移动一格,并退出循环
left+=1
break
return minvalue