leetcode HOT100 个人理解及解析
leetcode HOT100 个人理解及解析
- 1. 两数之和
- 1.1、题目
- 1.2、代码
- 1.3、思路
- 1.4、例子
- 2. 两数相加
- 2.1、题目
- 2.2、代码
- 2.3、解释
- 2.4、例子
- 3. 无重复字符的最长子串
- 3.1、题目
- 3.2、代码
- 3.3、解释
- 3.4、例子
1. 两数之和
链接
1.1、题目
给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。
你可以假设每种输入只会对应一个答案,并且你不能使用两次相同的元素。
你可以按任意顺序返回答案。
1.2、代码
class Solution:def twoSum(self, nums: List[int], target: int) -> List[int]:hashtable = dict() # 建立一个哈希表,用来存数值和下标的映射for i,num in enumerate(nums): # 遍历数组,i是下标,num是值if target-num in hashtable: # 如果 "target - 当前数" 已经在表里return [hashtable[target-num],i]hashtable[nums[i]] = i # 否则把当前数存到哈希表:值 -> 下标return [] # 如果没有找到,返回空数组
1.3、思路
两数之和(twoSum)整体流程
-
初始化
创建一个空的哈希表(字典),用来存储:数值 → 下标 -
遍历数组
用 for i, num in enumerate(nums) 遍历数组,i 表示下标num 表示当前的数值
-
计算差值
计算 target - num,
这个差值表示「需要另一个什么数」才能和当前数加起来等于目标值。 -
检查哈希表
判断这个差值是否已经在哈希表中:✅ 在表里 → 找到答案,返回 [之前那个数的下标, 当前下标]❌ 不在表里 → 把当前数和它的下标存进哈希表,继续遍历。
-
遍历结束
如果遍历完数组仍然没有找到符合条件的两个数 → 返回空数组 []。
1.4、例子
nums = [2, 7, 11, 15]
target = 91、i=0, num=2
计算 target - num = 9 - 2 = 7
7 不在 hashtable 里
存入 hashtable = {2: 0}2、i=1, num=7
计算 target - num = 9 - 7 = 2
2 在 hashtable 里(下标 0)
找到了!返回 [0, 1]
2. 两数相加
链接
2.1、题目
给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。
请你将两个数相加,并以相同形式返回一个表示和的链表。
你可以假设除了数字 0 之外,这两个数都不会以 0 开头。
2.2、代码
class Solution:def addTwoNumbers(self, l1: Optional[ListNode], l2: Optional[ListNode]) -> Optional[ListNode]:dummy = ListNode() # 建立一个哨兵节点(虚拟头结点),方便最后返回结果cur = dummy # cur 指针用于构建新链表carry = 0 # carry 表示进位,初始为 0# 只要 l1 没结束,l2 没结束,或者还有进位,就继续循环while l1 or l2 or carry:v1 = l1.val if l1 else 0 # 如果 l1 没结束,取节点值;否则取 0v2 = l2.val if l2 else 0 # 如果 l2 没结束,取节点值;否则取 0total = v1 + v2 + carry # 计算当前位的和(包含进位)carry = total // 10 # 更新进位val = total % 10 # 当前位的实际值(个位数)new_node = ListNode(val) # 建立新节点保存当前位的值cur.next = new_node # 把新节点接到结果链表后面cur = cur.next # cur 前进到新节点if l1: l1 = l1.next # 如果 l1 还有节点,前进if l2: l2 = l2.next # 如果 l2 还有节点,前进return dummy.next # 返回结果链表(从 dummy.next 开始)
2.3、解释
整体流程
- 初始化
- 建立一个虚拟头节点 dummy,并用指针 cur 指向它。
- 设置变量 carry = 0 表示进位。
- 循环相加
- 只要 l1 或 l2 没遍历完,或者 carry 不为 0,就继续循环。
- 每次循环:
- 从 l1 取值(若已结束取 0)。
- 从 l2 取值(若已结束取 0)。
- 计算 total = v1 + v2 + carry。
- 处理进位和当前位数值
- carry = total // 10 计算新的进位。
- val = total % 10 取当前位的实际值。
- 构建结果链表
- 创建一个新节点 ListNode(val)。
- 把它接到 cur 的后面。
- 移动 cur 指针到新节点。
- 链表前进
- 如果 l1 还有节点,前进到下一个节点。
- 如果 l2 还有节点,前进到下一个节点。
- 返回结果
- 当 l1、l2 都走完并且 carry = 0 时结束循环。
- 返回 dummy.next,即完整的结果链表。
2.4、例子
l1 = [2 → 4 → 3] # 表示数字 342
l2 = [5 → 6 → 4] # 表示数字 465运行过程:第一位:2 + 5 + 0 = 7 → 结果节点 7,进位 0
第二位:4 + 6 + 0 = 10 → 结果节点 0,进位 1
第三位:3 + 4 + 1 = 8 → 结果节点 8,进位 0[7 → 0 → 8] # 表示数字 807
3. 无重复字符的最长子串
链接
3.1、题目
给定一个字符串 s ,请你找出其中不含有重复字符的 最长 子串 的长度。
3.2、代码
class Solution:def lengthOfLongestSubstring(self, s: str) -> int:result = 0 # 最终结果(最长不重复子串的长度)s_dict = dict() # 哈希表:记录每个字符最近一次出现的位置begin = 0 # 滑动窗口左指针end = 0 # 滑动窗口右指针s_len = len(s) # 字符串长度for index, var in enumerate(s): # 遍历字符串,index是下标,var是字符if var not in s_dict: # 如果字符没出现过s_dict[var] = index # 记录它的位置else:tmp_var_index = s_dict[var] # 取出上次出现的位置s_dict[var] = index # 更新为当前位置if tmp_var_index >= begin: # 如果这个字符在当前窗口里出现过begin = tmp_var_index + 1 # 左指针跳到重复字符的下一个位置end = index # 更新右指针if end - begin + 1 > result: # 计算当前窗口的长度result = end - begin + 1 # 更新最大长度return result # 返回最长不重复子串的长度
3.3、解释
整体流程(Markdown 分点)
- 初始化
- result = 0:存储最长子串长度。
- s_dict = {}:字典,记录字符最近一次出现的位置。
- begin = 0:滑动窗口左边界。
- end = 0:滑动窗口右边界。
- 遍历字符串
- 使用 for index, var in enumerate(s) 遍历字符串:
- index 是位置
- var 是字符
- 检查字符是否重复
- 如果字符 var 没出现过 → 加入字典。
- 如果字符出现过:
- 取出它上次出现的位置 tmp_var_index。
- 更新 s_dict[var] = index。
- 如果 tmp_var_index >= begin,说明它在当前窗口中出现过 → 更新 begin = tmp_var_index + 1,跳过这个重复字符。
- 更新窗口右边界
- end = index 表示窗口右边界。
- 更新最大长度
- 当前窗口长度 = end - begin + 1。
- 如果比 result 大,就更新 result。
- 返回结果
- 遍历结束,返回 result,即最长不重复子串的长度。
3.4、例子
s = "abcabcbb"运行过程:index=0, var='a' → 没出现过,窗口 [0,0] → 长度 1 → result=1index=1, var='b' → 没出现过,窗口 [0,1] → 长度 2 → result=2index=2, var='c' → 没出现过,窗口 [0,2] → 长度 3 → result=3index=3, var='a' → 出现过,且在窗口内(位置 0),更新 begin=1 → 窗口 [1,3] → 长度 3index=4, var='b' → 出现过,且在窗口内(位置 1),更新 begin=2 → 窗口 [2,4] → 长度 3index=5, var='c' → 出现过,且在窗口内(位置 2),更新 begin=3 → 窗口 [3,5] → 长度 3index=6, var='b' → 出现过,且在窗口内(位置 4),更新 begin=5 → 窗口 [5,6] → 长度 2index=7, var='b' → 出现过,且在窗口内(位置 6),更新 begin=7 → 窗口 [7,7] → 长度 1最长不重复子串长度 = 3