文章目录
两数之和
1. 暴力解法
思路:通过双重循环遍历数组中所有可能的两个元素组合,检查其和是否等于目标值,若找到则返回对应索引。
代码实现:
class Solution(object):
def twoSum(self, nums, target):
"""
暴力解法 - 时间复杂度 O(n²),空间复杂度 O(1)
作为对比,提供暴力解法实现
"""
# 双重循环遍历所有可能的组合
for i in range(len(nums)):
for j in range(i + 1, len(nums)):
# 检查两个数的和是否等于目标值
if nums[i] + nums[j] == target:
return [i, j]
# 如果没有找到符合条件的两个数
return []
复杂度分析:
时间复杂度:O (n²),需双重循环遍历数组,n 为数组长度。
空间复杂度:O (1),无需额外存储空间。
2. 哈希表解法
思路:利用哈希表(Python 字典)存储已遍历元素的值和索引,遍历过程中计算当前元素与目标值的 “补数”(target - 当前元素),若补数已在哈希表中,则直接返回补数索引和当前元素索引,实现一次遍历完成查找。
代码实现:
class Solution(object):
def twoSum(self, nums, target):
# 哈希表解法 - 时间复杂度 O(n),空间复杂度 O(n)
# 使用字典存储已经遍历过的元素及其索引
# 键为元素值,值为元素索引
# 创建一个空字典用于存储已遍历的元素
num_dict = {}
# 遍历数组中的每个元素
for i, num in enumerate(nums):
# 计算需要的补数(target - 当前元素)
complement = target - num
# 检查补数是否已经在字典中
if complement in num_dict:
# 如果找到补数,返回补数的索引和当前元素的索引
return [num_dict[complement], i]
# 如果没有找到补数,将当前元素及其索引存入字典
num_dict[num] = i
# 如果没有找到符合条件的两个数(根据题目描述,这种情况不会发生)
return []在这里插入代码片
复杂度分析:
时间复杂度:O (n),仅需一次遍历数组,哈希表查找操作平均时间复杂度为 O (1)。
空间复杂度:O (n),最坏情况下需存储数组中所有元素(哈希表最多存储 n 个键值对)。
3. 哈希表解法的工作流程(示例)
以 nums = [2, 7, 11, 15],target = 9 为例:
第一轮迭代(i=0,num=2):
补数 = 9 - 2 = 7
7 不在空字典中,将 {2: 0} 存入字典。
第二轮迭代(i=1,num=7):
补数 = 9 - 7 = 2
2 在字典中(索引 0),返回 [0, 1]。
4. 为什么哈希表更快?
查找效率:哈希表的查找操作平均时间复杂度为 O (1),而数组遍历查找为 O (n)。
一次遍历:无需双重循环,仅需遍历数组一次即可完成查找。
即时判断:每遍历一个元素就可立即判断是否存在匹配的补数,无需等待后续元素。
5. 哈希函数的作用(Python 字典中)
将键(元素值)转换为哈希值,用于快速定位存储位置。
通过哈希值直接访问对应值(索引),实现 O (1) 级别的数据存取效率。
6. 两种解法的复杂度对比
解法 时间复杂度 空间复杂度 适用场景
暴力解法 O(n²) O(1) 数组规模极小(n 很小)
哈希表解法 O(n) O(n) 数组规模较大(需优化效率)
两数相加
算法思路
该解决方案通过同时遍历两个链表,逐位相加并处理进位来解决问题。时间复杂度为O(max(m, n)),空间复杂度为O(max(m, n))。
你可以直接运行Python文件查看测试结果,或者在浏览器中打开HTML文件体验交互式可视化。HTML页面已经打开,你可以在上面尝试不同的输入并查看算法的执行过程。
代码实现
class Solution:
def addTwoNumbers(self, l1: Optional[ListNode], l2: Optional[ListNode]) -> Optional[ListNode]:
# 初始化结果链表的头节点和当前节点
dummy_head = ListNode(0)
current = dummy_head
carry = 0 # 进位值
# 遍历两个链表,直到都为空
while l1 or l2:
# 获取当前节点的值,如果链表为空则为0
x = l1.val if l1 else 0
y = l2.val if l2 else 0
# 计算当前位的和以及进位
sum_val = x + y + carry
carry = sum_val // 10
current.next = ListNode(sum_val % 10)
# 移动到下一个节点
current = current.next
if l1:
l1 = l1.next
if l2:
l2 = l2.next
# 如果最后还有进位,需要添加新节点
if carry > 0:
current.next = ListNode(carry)
# 返回结果链表的头节点(跳过虚拟头节点)
return dummy_head.next
示例执行流程



309

被折叠的 条评论
为什么被折叠?



