【LeetCodeHot100 超详细Agent启发版本】两数之和 (Two Sum)

两数之和 (Two Sum)

虽然这是一道入门级的 LeetCode 题目,我不仅会带你通过面试的标准解法,更希望引导你从"检索与记忆"的角度来重新审视它。因为在我们的 Agent 设计中,高效的数据检索(无论是简单的哈希表还是复杂的向量数据库)是构建"长期记忆"的核心基石。

1. 算法分析:从 O(n2)O(n^2)O(n2) 到 O(n)O(n)O(n)

直觉解法 (Brute Force)

最直观的思路是双重循环:对于每一个数 x,我们遍历数组剩下的部分寻找 target - x。

时间复杂度: O(n2)O(n^2)O(n2)

评价: 在 AI 工程落地中,这种平方级复杂度是不可接受的。假设你的 Agent 有 100 万条记忆(Context),n2n^2n2 意味着万亿次计算,系统会直接卡死。

优化思路 (Space-Time Trade-off)

我们要找的是一个特定的"伴侣值":valneeded=target−valcurrentval_{needed} = target - val_{current}valneeded=target−valcurrent。

如果在遍历过程中,我们能以 O(1)O(1)O(1) 的时间复杂度询问:"我之前见过 valneededval_{needed}valneeded 吗?如果见过,它的下标是多少?"

这正是哈希表 (Hash Map) 的用武之地。在 Python 中,我们使用 dict。这在底层通常实现为哈希映射,平均查找时间为 O(1)O(1)O(1)。

2. 数学与逻辑推导

我们定义:

  • numsnumsnums 为输入向量
  • TTT 为目标值 (Target)
  • MMM 为哈希表,用于存储映射关系 {Value:Index}\{Value: Index\}{Value:Index}

对于数组中的第 iii 个元素 x=nums[i]x = nums[i]x=nums[i],我们需要寻找 yyy,使得:

x+y=T  ⟹  y=T−xx + y = T \implies y = T - xx+y=T⟹y=T−x

逻辑流如下:

  1. 初始化空哈希表 MMM
  2. 遍历数组,当前元素为 xxx,下标为 iii
  3. 计算需求值 y=T−xy = T - xy=T−x
  4. Query: 检查 yyy 是否存在于 MMM 中 (y∈M.keys()y \in M.keys()y∈M.keys())?
    • Hit (命中): 如果存在,说明之前已经遍历过 yyy(且下标为 M[y]M[y]M[y])。返回 [M[y],i][M[y], i][M[y],i]
    • Miss (未命中): 将当前元素 xxx 存入记忆 MMM,记录 M[x]=iM[x] = iM[x]=i

3. 代码优先 (Code-First) 实现

这是符合工业级标准的 Python 代码,包含了类型注解(Type Hinting),这是在编写大型 Agent 框架(如 LangChain)时的基本素养。

python 复制代码
from typing import List, Dict, Optional

class Solution:
    def twoSum(self, nums: List[int], target: int) -> List[int]:
        """
        使用哈希表在 O(n) 时间复杂度内解决两数之和。

        Args:
            nums: 整数列表
            target: 目标和

        Returns:
            包含两个索引的列表,这两个索引对应的数值之和等于 target。
        """
        # 这里的 map 充当了 Agent 的"短期记忆"
        # Key: 此时遍历过的数值 (Value)
        # Value: 该数值在数组中的原始索引 (Index)
        memory_map: Dict[int, int] = {}

        for i, num in enumerate(nums):
            # 计算我们需要寻找的"另一半"
            complement = target - num

            # 在记忆中检索 (Retrieval)
            if complement in memory_map:
                # 如果找到了,立即返回 [历史记忆的索引, 当前索引]
                return [memory_map[complement], i]

            # 如果没找到,将当前的信息"写入"记忆,供未来匹配使用
            memory_map[num] = i

        return []  # 根据题目描述,实际上不会执行到这里

# --- 单元测试 ---
if __name__ == "__main__":
    solver = Solution()
    test_nums = [2, 7, 11, 15]
    test_target = 9
    result = solver.twoSum(test_nums, test_target)
    print(f"Input: nums={test_nums}, target={test_target}")
    print(f"Output: {result}")  # 预期: [0, 1]

代码详细步骤解析

步骤 1: 导入类型提示模块
python 复制代码
from typing import List, Dict, Optional
  • 作用: 导入 Python 的类型提示工具
  • List : 用于标注列表类型,如 List[int] 表示整数列表
  • Dict : 用于标注字典类型,如 Dict[int, int] 表示键值都是整数的字典
  • Optional: 用于标注可选类型(虽然本例中未使用)
  • 意义: 类型注解是现代 Python 开发的最佳实践,能提高代码可读性和 IDE 智能提示
步骤 2: 定义解决方案类
python 复制代码
class Solution:
  • 作用: 创建一个类来封装解题方法
  • 意义: LeetCode 标准格式,便于组织代码和扩展
步骤 3: 定义核心方法
python 复制代码
def twoSum(self, nums: List[int], target: int) -> List[int]:
  • 参数说明 :
    • self: 类的实例引用
    • nums: List[int]: 整数列表,类型标注确保传入的是整数列表
    • target: int: 目标和,类型标注确保传入的是整数
  • 返回值 : List[int] 返回整数列表(包含两个索引)
  • 意义: 类型注解让函数契约清晰,减少运行时错误
步骤 4: 初始化哈希表(记忆系统)
python 复制代码
memory_map: Dict[int, int] = {}
  • 作用: 创建空字典作为"记忆存储"
  • 类型 : Dict[int, int] 表示键和值都是整数
  • 键 (Key): 存储已经遍历过的数值
  • 值 (Value): 存储该数值在原数组中的索引位置
  • 比喻: 这就像 Agent 的短期记忆,记录"我见过什么"以及"在哪里见到的"
步骤 5: 遍历数组
python 复制代码
for i, num in enumerate(nums):
  • enumerate(nums): 同时获取索引和值
  • i: 当前元素的索引(从 0 开始)
  • num: 当前元素的值
  • 意义: 一次性获取索引和值,避免手动维护索引计数器
步骤 6: 计算补数
python 复制代码
complement = target - num
  • 作用: 计算需要寻找的"另一半"
  • 数学原理 : 如果 num + complement = target,那么 complement = target - num
  • 例子: 如果 target=9,当前 num=2,那么 complement=7
  • 意义: 将问题转化为查找操作
步骤 7: 在记忆中检索
python 复制代码
if complement in memory_map:
  • 作用: 检查补数是否已经存在于哈希表中
  • 时间复杂度 : O(1)O(1)O(1) 平均情况
  • 返回: True 如果找到,False 如果未找到
  • 比喻: 就像问 Agent:"你之前见过这个数字吗?"
步骤 8: 命中时返回结果
python 复制代码
return [memory_map[complement], i]
  • memory_map[complement]: 获取补数在原数组中的索引(历史记忆)
  • i: 当前元素的索引
  • 返回 : [历史索引, 当前索引]
  • 例子: 如果 complement=7 在索引 1,当前在索引 0,返回 [1, 0]
  • 意义: 找到答案立即返回,无需继续遍历
步骤 9: 未命中时存储到记忆
python 复制代码
memory_map[num] = i
  • 作用: 将当前数字及其索引存入哈希表
  • : num(当前数字)
  • : i(当前索引)
  • 比喻: "记住这个数字,以后可能用得上"
  • 意义: 为未来的匹配做准备
步骤 10: 异常情况处理
python 复制代码
return []
  • 作用: 如果遍历完都没找到,返回空列表
  • 实际情况: 根据 LeetCode 题目保证,一定有解,这行代码不会执行
  • 意义: 防御性编程,处理边界情况
步骤 11: 单元测试
python 复制代码
if __name__ == "__main__":
    solver = Solution()
    test_nums = [2, 7, 11, 15]
    test_target = 9
    result = solver.twoSum(test_nums, test_target)
    print(f"Input: nums={test_nums}, target={test_target}")
    print(f"Output: {result}")  # 预期: [0, 1]
  • 作用: 验证代码正确性
  • 测试用例: nums=[2,7,11,15], target=9
  • 预期输出: [0, 1](因为 2+7=9)
  • 意义: 快速验证逻辑,便于调试

执行流程示例

nums = [2, 7, 11, 15], target = 9 为例:

迭代 i num complement memory_map (操作前) 检查结果 操作 memory_map (操作后)
1 0 2 7 {} 未找到 存储 2:0 {2:0}
2 1 7 2 {2:0} 找到 返回 [0,1] -

时间复杂度 : O(n)O(n)O(n) - 只需遍历一次
空间复杂度 : O(n)O(n)O(n) - 最坏情况需要存储 n-1 个元素

你可能会问:"SuanFaAgent,这只是一个简单的哈希查找,为什么你要提到 Agent?"

在构建 Autonomous Agents 时,我们经常面临一个核心问题:Retrieval (检索)

两数之和 (Exact Match)

题目本质是在寻找 A+B=TargetA + B = TargetA+B=Target。这是一种精确匹配。我们使用的是 Hash Map。

场景: 数据库查询,Function Calling 中的参数槽位精确匹配。

RAG 系统 (Semantic Match)

在 LLM 的 RAG (Retrieval-Augmented Generation) 架构中,我们面临的是更复杂的问题:给定用户的问题(Query),找出知识库中最相关的文档片段。

这里不再是简单的 a+b=targeta + b = targeta+b=target,而是寻找向量空间中的最近邻。

公式变了: 我们不再计算减法,而是计算余弦相似度 (Cosine Similarity):

Similarity(Q,K)=Q⋅K∥Q∥∥K∥Similarity(Q, K) = \frac{Q \cdot K}{\|Q\| \|K\|}Similarity(Q,K)=∥Q∥∥K∥Q⋅K

数据结构变了: 从 Python dict 变成了 Vector Database (如 Pinecone, Milvus) 或 ANN 算法 (如 HNSW)。

核心洞察

twoSum 中的 memory_map 其实就是一个微型的、精确匹配的"向量数据库"。你在做这道题时,实际上是在演练最基础的信息检索与存储机制。

如果不理解这种"用空间换时间"的哈希思想,就无法理解为什么我们在 RAG 中需要建立索引来加速检索。

5. 苏格拉底式总结 (Socratic Wrap-up)

现在你掌握了 O(n)O(n)O(n) 的哈希解法。为了检验你的举一反三能力,我想请你思考两个进阶问题:

场景变化

如果输入数组 nums 已经是有序的(例如 [2, 7, 11, 15]),你还需要使用哈希表吗?能否在 O(1)O(1)O(1) 的空间复杂度下完成?

提示: 双指针/Two Pointers

工程思考

在 twoSum 中,如果 nums 极其巨大,大到内存放不下这个 memory_map,但你需要处理海量查询,你会怎么设计系统?

提示: 这涉及到了分布式存储或布隆过滤器等概念

相关推荐
mikelv011 小时前
实现返回树状结构小记
java·数据结构
色空大师2 小时前
maven引入其他项目依赖爆红
java·maven
Ydwlcloud2 小时前
AWS 2026折扣活动深度解析:寻找最大优惠的智慧路径
大数据·服务器·人工智能·云计算·aws
NingboWill2 小时前
AI日报 - 2026年01月14日
人工智能
QYR_112 小时前
聚偏二氟乙烯(PVDF)行业市场深度调研与投资前景预测报告2026版
大数据·人工智能
2401_832298102 小时前
芯片级机密计算,天翼云CSV3筑牢数据“可用不可见”防线
大数据·网络·人工智能
Java后端的Ai之路2 小时前
【AI大模型开发】-Embedding 与向量数据库:从基础概念到实战应用
数据库·人工智能·embedding·向量数据库·ai应用开发工程师
我想发发发2 小时前
已经安装了ROS环境却还是报错`ModuleNotFoundError: No module named ‘rclpy‘`
前端·人工智能·chrome·机器人
yangminlei2 小时前
深入理解Sentinel:分布式系统的流量守卫者
java