3. 无重复字符的最长子串
直接通过遍历查找最长子串,因为是无重复字符,所以可以用set()
class Solution(object):
def lengthOfLongestSubstring(self, s):
"""
:type s: str
:rtype: int
"""
if not s: return 0
n=len(s)
ans=0
for i in range(n):
for j in range(i+1,n):
if len(set(s[i:j]))!=j-i:
break
ans=max(ans,j-i)
return ans
使用滑动窗口(个人感觉还是双指针):
如果右指针的数重复,左指针右移一格
如果不重复,右指针右移一格,比较字符串长度和最大长度
class Solution(object):
def lengthOfLongestSubstring(self, s):
"""
:type s: str
:rtype: int
"""
if not s: return 0
look = set()
ans = 0
n = len(s)
i, j = 0, 0
while j < n:
while j < n and s[j] not in look:
look.add(s[j])
ans = max(ans, j - i + 1)
j += 1
else:
look.remove(s[i])
i += 1
return ans
438. 找到字符串中所有字母异位词
滑动窗口就是双指针,右指针到p的长度时停下,如果窗口中字符串和p一样,就记录左指针的位置,否则左指针右移一位。
class Solution(object):
def findAnagrams(self, s, p):
"""
:type s: str
:type p: str
:rtype: List[int]
"""
m=len(s)
n=len(p)
shad=[0]*26
phad=[0]*26
ans=[]
i,j=0,0
for char in p:
phad[ord(char)-ord('a')]+=1
while j<m:
shad[ord(s[j])-ord('a')]+=1
if j-i+1==n:
if shad==phad:
ans.append(i)
shad[ord(s[i])-ord('a')]-=1
i+=1
j+=1
return ans
560. 和为 K 的子数组
注意k可以为0,而return的count初始值如果是0的话,需要考虑避免这个0的问题。
当前累积和为cumulative_sum, 初始为0。
初始化一个哈希表sum_count,存储里面所有可能的和的值(键)和它们的个数(值),初始为{0:1},因为cumulative_sum初始为0。
所以我们不考虑计算和是否为k,而是计算当前和-k是否出现在sum_count中。如果出现过,就代表当前和-之前一部分累积和=k。
更新sum_count。
class Solution(object):
def subarraySum(self, nums, k):
"""
:type nums: List[int]
:type k: int
:rtype: int
"""
sum_count = {0: 1} # 累积和: 计数
cumulative_sum = 0
count = 0
for num in nums:
cumulative_sum+=num
#检查之前的累积和
if cumulative_sum-k in sum_count:
count+=sum_count[cumulative_sum-k]
#更新哈希表
if cumulative_sum in sum_count:
sum_count[cumulative_sum]+=1
else:
sum_count[cumulative_sum]=1
return count
239. 滑动窗口最大值
算法:
滑动窗口遍历一次,每次数组中加入窗口中最大值, 但时间复杂度可能会随着输入数组的大小和窗口大小而变得很大。
创建一个单调递减的窗口遍历数组,始终保持最左侧的数是最大值,通过窗口遍历数组。
- 如果正在遍历的数大于窗口最右侧数,则窗口右侧缩小到窗口最小数≥这个数,形成单调递减。
- 将这个数加入窗口,如果窗口中数量大于k,移动窗口左侧。
- 如果窗口最右侧数的位置已经超过k,则窗口最左侧就是窗口的最大值。
from collections import deque
class Solution(object):
def maxSlidingWindow(self, nums, k):
"""
:type nums: List[int]
:type k: int
:rtype: List[int]
"""
if not nums:
return []
window = deque()
result = []
for i, num in enumerate(nums):
while window and nums[window[-1]] < nums[i]:
window.pop()
window.append(i)
while i - window[0] > k - 1:
window.popleft()
if i >= k - 1:
result.append(nums[window[0]])
return result
76. 最小覆盖子串
思路: 还是用双指针,一个数组table存储t的字母出现次数,一个数组stable存储存储s的字母出现次数,count计算子串中t的字母出现次数。
右指针遍历的字母:
更新stable,如果出现在table中, 更新count, while count==n:计算子串长度,和最小长度比较,如果更小就更新最小子串和最小长度; 左指针向右移动一位。
class Solution(object):
def minWindow(self, s, t):
"""
:type s: str
:type t: str
:rtype: str
"""
m=len(s)
n=len(t)
table=[0]*128
stable=[0]*128
left,right=0,0
ans=""
minlen=float('inf')
for char in t:
table[ord(char)]+=1
#记录当前窗口内字符的出现次数
count=0
while right<m:
#更新右指针所指字符串计数
stable[ord(s[right])]+=1
if stable[ord(s[right])]<=table[ord(s[right])]:
count+=1
while count==n:
if right-left+1<minlen:
minlen=right-left+1
ans=s[left:right+1]
stable[ord(s[left])]-=1
if stable[ord(s[left])]<table[ord(s[left])]:
count-=1
left+=1
right+=1
return ans