LeetCode3
思路分析
要找最长子串,需要直到无重复字符串的首和尾,然后再确定最长的那个,需要两个指针,可利用滑动窗口思想
方法1:集合
方法2:map
代码实现
方法1:集合
class Solution:
def lengthOfLongestSubstring(self, s: str) -> int:
if not s:
return 0
char_set = set()
left = 0
max_len = 0
for right in range(len(s)):
while s[right] in char_set:
char_set.remove(s[left])
left += 1
char_set.add(s[right])
max_len = max(max_len, len(char_set))
return max_len
方法2:map
class Solution:
def lengthOfLongestSubstring(self, s: str) -> int:
if len(s) == 0:
return 0
char_map = {}
max_len = 0
left = 0
for right in range(len(s)):
if s[right] in char_map:
left = max(left, char_map[s[right]] + 1)
char_map[s[right]] = right
max_len = max(max_len, right - left + 1)
return max_len
LeetCode159 至多包含两个不同字符的最长子串
给你一个字符串 s ,请你找出 至多 包含 两个不同字符 的最长子串,并返回该子串的长度。
https://leetcode.cn/problems/longest-substring-with-at-most-two-distinct-characters/
思路分析
仍然使用 left 和 right 来锁定一个窗口,然后一边向右移动一边分析
我们接下来需要解决两个问题
怎么判断只有两个元素?
还是hash好用,每一个时刻,hashmap包括不超过3个元素
判断移除谁,移除后left是什么?
设计一下hashmap的key-value的含义,key:字符,value:窗口中最右边的字符位置
del_idx = min(hashmap.values())
del hashmap[s[del_idx]]
left = del_idx + 1
代码实现
class Solution:
def lengthOfLongestSubstringTwoDistinct(self, s: str) -> int:
if len(s) < 3:
return len(s)
char_map = {}
max_len = 0
left = 0
for right in range(len(s)):
if len(char_map) < 3:
char_map[s[right]] = right
if len(char_map) == 3:
del_idx = min(char_map.values())
del char_map[s[del_idx]]
left = del_idx + 1
max_len = max(max_len, right - left + 1)
return max_len
LeetCode340
https://leetcode.cn/problems/longest-substring-with-at-most-k-distinct-characters/description/
思路分析
与上一题类似,只要把2改为k即可
代码实现
class Solution:
def lengthOfLongestSubstringKDistinct(self, s: str, k: int) -> int:
if len(s) < k+1:
return len(s)
char_map = {}
max_len = 0
left = 0
for right in range(len(s)):
if len(char_map) < k+1:
char_map[s[right]] = right
if len(char_map) == k+1:
del_idx = min(char_map.values())
del char_map[s[del_idx]]
left = del_idx + 1
max_len = max(max_len, right - left + 1)
return max_len
LeetCode209
https://leetcode.cn/problems/minimum-size-subarray-sum/
思路分析
本题可以使用双指针来解决,也可视为队列法
基本思路如下
先让元素不断入队,当入队元素和大于等于target是记录一下此时队列的容量
如果队列元素之和大于等于target则开始出队,直到小于target再入队
代码实现
class Solution:
def minSubArrayLen(self, target: int, nums: List[int]) -> int:
left = 0
min_len = len(nums) + 1
total = 0
for right in range(len(nums)):
total += nums[right]
while total >= target:
min_len = min(min_len, right - left + 1)
total -= nums[left]
left += 1
return min_len if min_len <= len(nums) else 0
LeetCode11
https://leetcode.cn/problems/container-with-most-water/
思路分析
盛水的体积的计算:短板的高度*长短板之间的宽度
S(left, right) = min(h[left], h[right])(right - left)
长短板分列最左边和最右边,宽度最大,此时长板或短板向中间收窄,宽度会变小,此时板的高度
具体执行
代码实现
class Solution:
def maxArea(self, height: List[int]) -> int:
left, right = 0, len(height)-1
s = 0
while left < right:
s = max(s, min(height[left], height[right]) * (right - left))
if height[left] < height[right]:
left += 1
else:
right -= 1
return s
异位词(排列)
如果两个字符串仅仅是字母出现的位置不一样,则称两者互为对方的一个排列,也称异位词
如何判断?
LeetCode 567
https://leetcode.cn/problems/permutation-in-string/
思路分析
代码实现
python中字母与ascii转换 chr() ord()
class Solution:
def checkInclusion(self, s1: str, s2: str) -> bool:
n1, n2 = len(s1), len(s2)
if n1 > n2:
return False
char_arr1 = [0] * 26
char_arr2 = [0] * 26
for i in range(n1):
char_arr1[ord(s1[i]) - ord('a')] += 1
char_arr2[ord(s2[i]) - ord('a')] += 1
if char_arr1 == char_arr2:
return True
left = 0
for right in range(n1, n2):
char_arr2[ord(s2[right]) - ord('a')] += 1
char_arr2[ord(s2[left]) - ord('a')] -= 1
left += 1
if char_arr1 == char_arr2:
return True
return False
LeetCode438
https://leetcode.cn/problems/find-all-anagrams-in-a-string/
思路分析
思路分析同上题一致,多加了一步进行处理
增加了一个列表,记录出现异位词的位置,如果出现了,将其加到列表中
代码实现
class Solution:
def findAnagrams(self, s: str, p: str) -> List[int]:
n1, n2 = len(p), len(s)
if n1 > n2:
return []
res = []
char_arr1 = [0] * 26
char_arr2 = [0] * 26
for i in range(n1):
char_arr1[ord(p[i]) - ord('a')] += 1
char_arr2[ord(s[i]) - ord('a')] += 1
if char_arr1 == char_arr2:
res.append(0)
left = 0
for right in range(n1, n2):
char_arr2[ord(s[right]) - ord('a')] += 1
char_arr2[ord(s[left]) - ord('a')] -= 1
left += 1
if char_arr1 == char_arr2:
res.append(left)
return res
class Solution:
def findAnagrams(self, s: str, p: str) -> List[int]:
p_len, s_len = len(p), len(s)
if p_len > s_len:
return []
res = []
p_count = [0] * 26
s_count = [0] * 26
for i in range(p_len):
p_count[ord(p[i]) - ord('a')] += 1
s_count[ord(s[i]) - ord('a')] += 1
if p_count == s_count:
res.append(0)
for i in range(s_len - p_len):
s_count[ord(s[i + p_len]) - ord('a')] += 1
s_count[ord(s[i]) - ord('a')] -= 1
if p_count == s_count:
res.append(i + 1)
return res