while left < right: 操作s[加减] 比如s是累计窗口内的和或者用来保存出现次数的字典 条件s[判断s是否符合条件] 条件1: left + 1 条件2: right -1
右边按照1步慢慢来移动,左边自适应移动代码规律如下
1 2 3 4 5 6 7 8
for right inrange(n): # 1. 先操作 s = s + nums[right]【题目3209904】或者不操作【题目262780】 # 2. 循环左 while condition(s)【题目3209904】 或者 if 【题目262780】 操作s 保存结果ans left = left + 1
长度最小的子数组[209]
这是很简单的滑动窗口,没有复杂的逻辑,就是简答的滑窗,代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
classSolution: defminSubArrayLen(self, target: int, nums: List[int]) -> int: start, end = 0, 0 s = 0 min_lens = float("inf") while end < len(nums): s += nums[end] while s >= target: # 刚好满足条件了 if end - start + 1 < min_lens: min_lens = end - start + 1 s -= nums[start] start += 1 end += 1 if min_lens==float("inf"): return0 else: return min_lens
classSolution: deflengthOfLongestSubstring(self, s: str) -> int: # 删除字典元素 defremove_d_v(d,v): if v in d: d[v] -= 1 if d[v]==0: d.pop(v) # 开始逻辑 iflen(s)==1:return1 from collections import defaultdict start, end = 0,0 d = defaultdict(int) max_lens = 0 while end < len(s): while s[end] in d: # 刚好不满足条件了 max_lens = max(max_lens, end - start) remove_d_v(d,s[start]) start += 1 d[s[end]] += 1# 注意点,位置放这里 end += 1 returnmax(max_lens, end - start)
classSolution: deflongestDupSubstring(self, s: str) -> str: ans = "" start = 0 end = 1 n = len(s) while start < n: while s[start:end] in s[start+1:]: if end - start> len(ans): ans = s[start:end] end += 1 start += 1 end += 1 return ans
大部分题解是while end < n
和大于等于 target 的最短子数组[LCR 008]
题解如下,注意一下边界的条件
1 2 3 4 5 6 7 8 9 10 11 12 13 14
classSolution: defminSubArrayLen(self, target: int, nums: List[int]) -> int: import bisect prefix = [0] for i in nums: prefix.append(prefix[-1] + i) if prefix[-1]<target: return0 res = float("inf") for i inrange(len(prefix)): index = bisect.bisect_left(prefix, prefix[i] + target) if index != len(prefix): res = min(index - i, res) return0if res==len(prefix) else res
也可以使用滑窗解法如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
class Solution: def minSubArrayLen(self, s: int, nums: List[int]) -> int: if not nums: return 0 n = len(nums) ans = n + 1 start, end = 0, 0 total = 0 while end < n: total += nums[end] while total >= s: ans = min(ans, end - start + 1) total -= nums[start] start += 1 end += 1 return 0 if ans == n + 1 else ans
# bisect 因此nums都是正数,所以可以使用二分查找来做 classSolution: defminOperations(self, nums: List[int], x: int) -> int: defget_prefix_sum(nums): prefix = [] for i in nums: val = prefix[-1] if prefix else0 prefix.append(i+val) return prefix
res = float("inf") for i inrange(len(nums)): nums2 = nums[0:i][::-1] + nums[i:][::-1] prefix = get_prefix_sum(nums2) print(prefix) if x in prefix: res = min(res, prefix.index(x)+1) return -1if res==float("inf") else res # 滑窗 classSolution: defminOperations(self, nums: List[int], x: int) -> int: diff = sum(nums) - x if diff < 0: return -1 left = 0 right = 0 sm = 0 res = -1 while right < len(nums): sm += nums[right] while sm > diff: sm -= nums[left] left += 1 if sm == diff: res = max(res,right - left + 1) right += 1# 一定放这里 return -1if res==-1elselen(nums)-res
# 错误 classSolution: defmaxDistance(self, nums1: List[int], nums2: List[int]) -> int: left = 0 right = 0 res = 0 while right < len(nums2): while left < len(nums1) and nums1[left] > nums2[right] and left<=right: left += 1 res = max(res, right-left) right += 1 return res # 正确 classSolution: defmaxDistance(self, nums1: List[int], nums2: List[int]) -> int: left = 0 right = 0 res = 0 while right < len(nums2): while left < len(nums1) and nums1[left] > nums2[right] and left<=right: left += 1 if left < len(nums1): # 这里要加一个 res = max(res, right-left) right += 1 return res
left = ans = 0 for right, x inenumerate(fruits): cnt[x] += 1#这里字典操作 whilelen(cnt) > 2: cnt[fruits[left]] -= 1 if cnt[fruits[left]] == 0: cnt.pop(fruits[left]) left += 1 ans = max(ans, right - left + 1) return ans
classSolution: deffindAnagrams(self, s: str, p: str) -> List[int]: s_list = [0] * 26 p_list = [0] * 26 for n in p: p_list[ord(n)-ord('a')] += 1 left=0 right=0 ans = [] while right < len(s): s_list[ord(s[right])-ord("a")] += 1 if right - left >= len(p): # 发现右比左多的话,左边也动 s_list[ord(s[left])-ord("a")] -= 1 left = left + 1 if s_list == p_list: ans.append(left) right = right + 1
classSolution: deffindSubstring(self, s: str, words: List[str]) -> List[int]: p = "".join(words) s_list = [0] * 26 p_list = [0] * 26 for n in p: p_list[ord(n) - ord('a')] += 1 left = 0 right = 0 ans = [] while right < len(s): s_list[ord(s[right]) - ord("a")] += 1 if right - left >= len(p): s_list[ord(s[left]) - ord("a")] -= 1 left = left + 1 if s_list == p_list: d = Counter(words) # 开始一步一步查验是否存在 for j inrange(left, left + len(words) * len(words[0]), len(words[0])): if s[j:j + len(words[0])] in words: d[s[j:j + len(words[0])]] -= 1 ifall([i==0for i inlist(d.values())]): ans.append(left) right = right + 1 return ans
classSolution: defisPalindrome(self, s: str) -> bool: left = 0 right = len(s) - 1 while left < right: while left < right and left < len(s) andnot s[left].isalpha() andnot s[left].isdigit(): left = left + 1 while left < right and right < len(s) andnot s[right].isalpha() andnot s[right].isdigit(): right = right-1 if s[left].lower() == s[right].lower(): left = left + 1 right = right - 1 else: print(left, right) returnFalse returnTrue
classSolution: defremoveElement(self, nums: List[int], val: int) -> int: left = 0 for right inrange(len(nums)): pass#这里不需要操作啥 if nums[right] == val: continue nums[left] = nums[right] left = left + 1 return left
classSolution: defremoveDuplicates(self, nums: List[int]) -> int: left = 0 for right inrange(0, len(nums)): if nums[right] == nums[left]: continue left = left + 1 nums[left] = nums[right] return left + 1
classSolution: defremoveDuplicates(self, nums: List[int]) -> int: from collections import defaultdict left = 0 d = defaultdict(int) for right inrange(len(nums)): d[nums[right]] = d[nums[right]] + 1# 注意点,先加1,然后再判断 if d[nums[right]] > 2: continue nums[left] = nums[right] left = left + 1 return left
classSolution: defrotate(self, nums: List[int], k: int) -> None: """ Do not return anything, modify nums in-place instead. """ if k==0orlen(nums)==1: return k = k % len(nums) num2 = nums[-k:] + nums[0:-k] # 注意 for index, value inenumerate(num2): nums[index] = value
classSolution: deftwoSum(self, nums: List[int], target: int) -> List[int]: d = {} for i inrange(len(nums)): d[nums[i]] = i for i inrange(len(nums)): current_value = nums[i] if target - current_value in d: if d[target - current_value]!= i: return [i, d[target - current_value]]
两数之和II[167]
1 2 3 4 5 6
classSolution: deftwoSum(self, numbers: List[int], target: int) -> List[int]: d=dict(zip(numbers,list(range(len(numbers))))) for i inrange(len(numbers)): if (target-numbers[i]) in d: return [i+1,d[target-numbers[i]]+1]
classSolution: defthreeSum(self, nums: List[int]) -> List[List[int]]: ifnot nums: return [] nums.sort() if nums[0] == 0and nums[-1] == 0andlen(nums) >= 3: return [[0, 0, 0]] res = [] for i inrange(len(nums) - 2): if nums[i] > 0: break if i >= 1and nums[i - 1] == nums[i]: continue m, n = i + 1, len(nums) - 1 while m < n: s = nums[i] + nums[m] + nums[n] if s < 0: m = m + 1 elif s > 0: n = n - 1 else: res.append([nums[i], nums[m], nums[n]]) m = m + 1 n = n - 1 while m < n and nums[m] == nums[m - 1]: # 注意,不是m+1,是从后往前去你有没有重复的 m = m + 1 while m < n and nums[n] == nums[n + 1]: n = n - 1 return res
classSolution: deffullJustify(self, words: List[str], maxWidth: int) -> List[str]: left = 0 right = 0 res = [] while left < len(words) and right < len(words): str_sums = 0 while right < len(words) and str_sums + len(words[right]) + right - left <= maxWidth: # 注意这里直接加上去 str_sums = str_sums + len(words[right]) right = right + 1 res.append(words[left:right]) left = right new_list = [] for i in res[:-1]: diff = maxWidth - len("".join(i)) for lens inrange(diff): index = lens % max(1, (len(i) - 1)) i[index] = i[index] + " " new_list.append("".join(i)) new_list.append(" ".join(res[-1]) + " "*(maxWidth-len(" ".join(res[-1])))) return new_list
classSolution: deftrainingPlan(self, actions: List[int]) -> List[int]: i, j = 0, len(actions) - 1 while i < j: while i < j and actions[i] & 1 == 1: i += 1 while i < j and actions[j] & 1 == 0: j -= 1 actions[i], actions[j] = actions[j], actions[i] return actions
classSolution: defmaxArea(self, height: List[int]) -> int: left = 0 right = len(height) - 1
area = 0 while left <= right: temp = min(height[left], height[right]) * (right - left) if height[left] < height[right]: left = left + 1 else: right = right - 1 if temp > area: area = temp return area
classSolution: defreverseWords(self, s: str) -> str: left = 0 right = 0 res = [] while left < len(s) and right < len(s): while left < len(s) and s[left] == " ": left = left + 1 right = left while right < len(s) and s[right] != " ": right = right + 1 res.append(s[left:right]) left = right return" ".join(res[::-1]).strip()
classSolution: defisPalindrome(self, s: str) -> bool: left = 0 right = len(s) - 1 while left < right: while left < right and left < len(s) andnot s[left].isalpha() andnot s[left].isdigit(): #注意点1 left = left + 1 while left < right and right < len(s) andnot s[right].isalpha() andnot s[right].isdigit(): right = right-1 if s[left].lower() == s[right].lower(): left = left + 1 right = right - 1 else: print(left, right) returnFalse returnTrue