【如果笔记对你有帮助,欢迎关注&点赞&收藏,收到正反馈会加快更新!谢谢支持!】
ps:笔记和代码按本人理解整理,重思路
目录
一、哈希表
题目1:两数之和
- 题意:在nums中找到和为 target 的两个数的index
- 拆解:
for idx, num in enumerate(nums): - mapping[哈希表] 记录 {target—当前num[key]: 当前idx[value]} if num在mapping.keys()中: # 说明已有“当前num+之前num == target”,满足条件 - 返回结果[当前idx,mapping]
- 代码:
class Solution: def twoSum(self, nums: List[int], target: int) -> List[int]: n = len(nums) mapping = {} for i in range(n): if target - nums[i] in mapping: return [mapping[target - nums[i]], i] else: mapping[nums[i]] = i
题目2:字母异位词分组
- 题意:将组成字母一致的单词归位一组
- 关键:
"ate","eat","tea"
这三个字符串在sort后都是"aet"
【哈希表为 {["aet"
: ["ate","eat","tea"
], ……}】 - 代码:
class Solution: def groupAnagrams(self, strs: List[str]) -> List[List[str]]: d = defaultdict(list) for str_ in strs: sorted_str = ''.join(sorted(str_)) d[sorted_str].append(str_) return list(d.values())
题目3:最长连续序列
- 题意:找到数组(可能有重复)中连续的最长序列,要求时间复杂度为O(n) 【所以不能排序】
- 拆解:
「哈希表确定」st = set(nums) 「目标」找到连续序列的第一个数,即(num-1)不存在 「逻辑」 for st中的每个数num: if 是序列的第一个: - 计算当前序列长度 - 更新答案 「注意」遍历元素的时候,要遍历哈希集合,不能是nums,不然循环次数会变成O(n^2)
- 代码:
class Solution: def longestConsecutive(self, nums: List[int]) -> int: max_len = 0 st = set(nums) for num in st: if num - 1 in st: # 不是连续序列的第一个,跳过 continue y = num + 1 while y in st: y += 1 max_len = max(max_len, y-num) return max_len
二、双指针
题目4:移动零
- 题意:把数组中的0移动到末尾,同时保持非零元素的相对顺序
- 拆解:
「双指针类型」快慢指针 「快指针作用」遍历数组的元素 「慢指针作用」重写数组 「逻辑」 初始化:快慢指针在第一个数位置 while/for 快指针遍历数组: if 快指针指向0: 快指针前进 else 快指针指向非0: - nums[慢指针]的值改写成nums[快指针]的值(慢指针负责改写数组) - 快、慢指针都前进 for 慢指针到结尾的数: - 改为0
- 代码:
class Solution: def moveZeroes(self, nums: List[int]) -> None: """ Do not return anything, modify nums in-place instead. """ slow = 0 fast = 0 while fast < len(nums): if nums[fast] != 0: nums[slow] = nums[fast] slow += 1 fast += 1 for i in range(slow, len(nums)): nums[i] = 0 return nums
题目5:盛最多水的容器
- 题意:求面积 H(y轴) * W(x轴),其中 H = min(左高度,右高度),W = 双指针距离
- 关键:移动指针的时候 W一定减小,看 H 有没有可能增加(所以保留高的,移动低的)
- 拆解:
「双指针类型」左右指针 「代码逻辑」 初始化:左、右指针分别在最左、最右端 while 左指针在左、右指针在右: - 计算面积 = min(左高度,右高度) * 左右指针距离 - 更新最大面积 - 移动高度小的指针(左指针向 -> 或者 右指针向 <- )
- 代码:
class Solution: def maxArea(self, height: List[int]) -> int: l = 0 r = len(height)-1 result = 0 while l < r: area = (r-l)*min(height[l], height[r]) result = max(result, area) if height[r] < height[l]: r -= 1 else: l += 1 return result
题目6:三数之和
- 题意:所有和为 0 且不重复的三元组 → A + B + C = 0
- 拆解:
「双指针类型」左右指针 「代码逻辑」 - nums排序 -> 有序数组 for 遍历第一个数A(固定A,转化成B+C=-A的两数之和问题): - 去重1:重复的A - 剪枝:A > 0,因为排序后 C > B > A > 0,不可能有三数之和为0 # 左右双指针找A+B+C=0 while 左指针在左、右指针在右: if 总和 > 0: 右指针⬅️移 elif 总和 < 0: 左指针右移 elif 总和为0: - [A, B, C]加到结果 # 找下一个解 - 去重2:重复的B和C跳过 - 左、右指针同时右移、左移
- 代码:
class Solution: def threeSum(self, nums: List[int]) -> List[List[int]]: result = [] nums = sorted(nums) for i in range(len(nums)-2): # 注释中 A=nums[i] if i > 0 and nums[i] == nums[i-1]: # 重复情况 continue if nums[i] > 0: # 因为 C>B>A>0,三数之和不可能为0,直接结束 return result # 开始两数之和 left = i+1 right = len(nums)-1 while left < right: sum_ = nums[i]+nums[left]+nums[right] if sum_ > 0: right -= 1 elif sum_ < 0: left += 1 else: result.append([nums[i], nums[left], nums[right]]) # 因为这题可能有多个答案,要找出所有答案 # 找到一个解之后怎么找下一个解:跳过重复数字 → 左右指针同时右移和左移 while left < right and nums[left] == nums[left+1]: # 跳过重复数字 left += 1 while left < right and nums[left] == nums[right-1]: # 跳过重复数字 right -= 1 left += 1 right -= 1 return result
题目7:接雨水
- 题意:找最多接水量
- 关键:单位柱子能接的雨水量 = min(左侧最高柱,右侧最高柱) - 当前高度
- 拆解:
「双指针类型」左右指针 「左指针作用」记录左侧最高 「右指针作用」记录右侧最高 「代码逻辑」 - 初始化左右侧最高为-inf while 左指针在左、右指针在右: if 左侧最高 < 右侧最高: # 移动左指针 if 左指针位置能存水(即,左指针水位 < 左侧最高): - 记录左指针位置存水量 else: # 左指针位置不能存水(即,左指针水位 >= 左侧最高) - 更新左侧最高水位 - 左指针右移 if 左侧最高 >= 右侧最高: 同理
- 代码:
class Solution: def trap(self, height: List[int]) -> int: result = 0 left = 0 right = len(height)-1 height_l = height_r = -inf # 初始化 while left <= right: if height_l <= height_r: # 左端低,处理左边,移动左指针 if height[left] < height_l: # 当前柱子高度<左侧最高,可以存水 result += (height_l - height[left]) # 记录存水量 else: # 当前柱子高度>=左侧最高>=右侧最高,不能存水 height_l = height[left] # 更新左侧最高 left += 1 else: if height[right] < height_r: # 右端低,处理右边,移动右指针 result += (height_r - height[right]) else: height_r = height[right] right -= 1 return result