1、leetcode3给定一个字符串s,请你找出其中不含有重复字符的最长子串的长度,该题可以一边遍历,一边新建一个已查看的列表,如果先出现的字符在已查看的列表当中,则不断删除已查看列表直到无重复,同时不断记录列表最大长度即可,代码参考如下:
class Solution:
def lengthOfLongestSubstring(self, s: str) -> int:
if not s:
return 0
look_up = []
n = len(s)
cur_len = 0
max_len = 0
for i in range(n):
while s[i] in look_up:
look_up.pop(0)
cur_len -= 1
cur_len += 1
look_up.append(s[i])
max_len = max(max_len, cur_len)
return max_len
同时,因为用列表记录删除时速度比较慢,可以使用hash表进行存储来优化速度,但是由于hash表的无序性,需要额外记录left下标来标记删除的元素。
class Solution:
def lengthOfLongestSubstring(self, s: str) -> int:
if not s:
return 0
look_up = set()
n = len(s)
cur_len = 0
max_len = 0
left = 0
for i in range(n):
while s[i] in look_up:
look_up.remove(s[left])
cur_len -= 1
left +=1
cur_len += 1
look_up.add(s[i])
max_len = max(max_len, cur_len)
return max_len
2、Leetcode11,给定一个长度为n的整数数组height。有n条垂线,第i条线的两个端点是(i,0)和(i,height[i]),找出其中的两条线,使得它们与x轴共同构成的容器可以容纳最多的水,返回容器可以存储的最大水量。设两指针为i,j,指向的水槽板的高度分别是h[i]和h[j],此状态下水槽的面积为S(i,j)=min(h[i], h[j]) x (j - 1),在每个状态下无论长版或者短板向中间收窄一格,到会导致水槽底边宽度-1变短,因此只有箱内移动短板,水槽的面积才可能会增大,因此循环每轮将短板移动一个,并更新面积最大值,直到两个指针相遇后跳出,即可获得最大面积,代码参考如下:
class Solution:
def maxArea(self, height: List[int]) -> int:
i, j = 0, len(height)-1
max_area = 0
while i < j:
area = min(height[i], height[j]) * (j - i)
max_area = max(max_area, area)
if height[i] <= height[j]:
i += 1
else:
j -= 1
return max_area
3、寻找子串异位词,Leetcode567,本题可以以s1的大小截图为一个固定的窗口,一遍向右移动一边比较是否相同即可,比较方法可以构造字母和数量对应关系的字典,比较两个字典是否相同。
class Solution:
def checkInclusion(self, s1: str, s2: str) -> bool:
n1 = len(s1)
n2 = len(s2)
dic1 = {}
for i in range(n1):
if s1[i] not in dic1:
dic1[s1[i]] = 1
else:
dic1[s1[i]] += 1
for i in range(n2-n1+1):
dic2 = {}
for j in range(i,i+n1):
if s2[j] not in dic2:
dic2[s2[j]] = 1
else:
dic2[s2[j]] += 1
if dic1 == dic2:
return True
return False
但是这样速度太慢,每次dic2都需要重复的构造n1长度的字典,其实可以直接构造长度为26的两个字典,然后通过滑动的办法判断是否为异位词即可大幅优化速度,代码参考如下:
class Solution:
def checkInclusion(self, s1: str, s2: str) -> bool:
n1 = len(s1)
n2 = len(s2)
dic1 = [0]*26
dic2 = [0]*26
if n2 < n1:
return False
for c in s1:
dic1[ord(c)-ord('a')] += 1
for i in range(n1):
dic2[ord(s2[i])-ord('a')] += 1
if dic1 == dic2:
return True
for i in range(n1,n2):
dic2[ord(s2[i])-ord('a')] += 1
dic2[ord(s2[i-n1])-ord('a')] -= 1
if dic1 == dic2:
return True
return False
4、Leetcode438,找到所有字母异位,只需要将上一题改成用一个List存储结果即可,代码参考如下:
class Solution:
def findAnagrams(self, s: str, p: str) -> List[int]:
n1 = len(p)
n2 = len(s)
dic1 = [0]*26
dic2 = [0]*26
if n2 < n1:
return []
res = []
for c in p:
dic1[ord(c)-ord('a')] += 1
for i in range(n1):
dic2[ord(s[i])-ord('a')] += 1
if dic1 == dic2:
res.append(0)
for i in range(n1,n2):
dic2[ord(s[i])-ord('a')] += 1
dic2[ord(s[i-n1])-ord('a')] -= 1
if dic1 == dic2:
res.append(i-n1+1)
return res