【LeetCode 题解】两数之和(C++/Python 双解法):从语法到算法的全面解析

news2025/7/21 17:31:20

【LeetCode题解】两数之和(C++/Python双解法):从语法到算法的全面解析

一、题目描述

题目链接:1. 两数之和
难度:简单
要求:给定一个整数数组 nums 和一个整数目标值 target,在数组中找出两个数,使其和为 target,并返回它们的下标。
限制:每个输入只对应唯一解,且不能重复使用同一个元素。

二、解法思路:哈希表(最优解)

2.1 核心思想

  • 暴力枚举:遍历每个元素,再嵌套遍历寻找补数(target - nums[i]),时间复杂度为 O(n²),效率低。
  • 哈希表优化:用哈希表(字典)存储元素及其下标,遍历数组时,对每个元素 nums[i],检查补数是否已在哈希表中:
    • 若存在,直接返回补数的下标和当前下标。
    • 若不存在,将当前元素和下标存入哈希表,供后续元素查找。
  • 时间复杂度:O(n),只需遍历数组一次。
  • 空间复杂度:O(n),哈希表存储最多 n 个元素。

2.2 哈希表原理图解

哈希表查找补数示意图

三、代码实现

3.1 Python 解法

常规版(适合LeetCode直接提交)
from typing import List

class Solution:
    def twoSum(self, nums: List[int], target: int) -> List[int]:
        d = {}  # 键:元素值,值:下标
        for i in range(len(nums)):
            complement = target - nums[i]
            if complement in d:
                return [d[complement], i]
            d[nums[i]] = i
        return []  # 题目保证有解,此句可省略
ACM版(适合本地ACM模式输入)
# 读取输入
import sys

def main():
    data = list(map(int, sys.stdin.read().split()))
    n = data[0]
    target = data[1]
    nums = data[2: 2+n]
    
    d = {}
    for i in range(n):
        complement = target - nums[i]
        if complement in d:
            print(d[complement], i)
            return
        d[nums[i]] = i

if __name__ == "__main__":
    main()

ACM输入说明

  • sys.stdin.read() 读取全部输入,适用于多行或连续输入场景。
  • 输入格式示例:4 9 2 7 11 15(依次为n, target, 数组元素)。

3.2 C++ 解法

#include <iostream>
#include <unordered_map>
#include <vector>
using namespace std;

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        unordered_map<int, int> numToIndex; // 哈希表:存储元素值到下标的映射
        for (int i = 0; i < nums.size(); i++) {
            int complement = target - nums[i];
            // 查找补数是否在哈希表中
            if (numToIndex.find(complement) != numToIndex.end()) {
                return {numToIndex[complement], i}; // C++11列表初始化
            }
            numToIndex[nums[i]] = i; // 存入当前元素和下标
        }
        return {}; // 题目保证有解,此句可省略
    }
};

// 主函数(ACM输入模式)
int main() {
    int n, target;
    cin >> n >> target; // 读取n和target
    vector<int> nums(n); // 创建长度为n的数组
    for (int i = 0; i < n; i++) {
        cin >> nums[i]; // 读取数组元素
    }
    
    Solution solution;
    vector<int> result = solution.twoSum(nums, target);
    
    cout << result[0] << " " << result[1] << endl; // 输出结果
    return 0;
}
// #include <xxx> 引入工具包 
#include <iostream>         // 输入输出 cin >> 输入  cout << 输出
#include <unordered_map>    // 哈希工具包, 快速查询字典
#include <vector>           // 动态工具包, 存储一组数组

using namespace std;         // 简化代码, 标准库工具。后面用到工具时, 不用写std:: 前缀


// 类和函数!
class Solution {             // class是模板, Solution是模板名字
    // 比如“汽车”是个模板, 里面包含"启动", "刹车"等功能
public:     //模板里面的功能默认是“私有的”, public 让后面的函数可以被外部调用!
    vector<int> twoSum(vector<int>& nums, int target) {
        /*  vector<int> twoSum(...) 表示twoSum这个函数的返回值是一组整数(动态数组) vector<int>
            twoSum 函数名称
            vector<int>& nums 是函数输入的一组整数(vector<int>)
            & 表示“引用”, 直接使用原始数据, 不复制一份
            int target 另一个输入参数  */
        unordered_map<int, int> numToIndex; // 创建一个哈希表 <数字, 下标>
        for (int i = 0; i < (int)nums.size(); i++) {
            // for (起点 ; )
            int complement = target - nums[i]; // 计算需要的补数 
            // numToIndex.find(complement) 是在哈希表中查找是否有“单词”(“键值对中的键”)等于complement
            // 如果find到complement:返回这个单词对应的条目
            // 如果没找到,返回一个特殊标记 告诉我们 字典中没有这个单词!
            // end()方法: 是一个虚拟位置,字典的最后一个条目的后面 就是空!
            // 所以 如果find(xx) == end()  就是没找到这个单词
            if (numToIndex.find(complement) != numToIndex.end()) {
                // 如果补数complement就在哈希表中,如果找到了 且不等于end()
                return { numToIndex[complement], i };
            }
            // 如果没找到,把当前数和下标放入哈希表
            numToIndex[nums[i]] = i;
        }
        return {};
    }
};

// main()函数是程序的入口
int main(){
    int n, target;
    cin >> n >> target; // cin >> ... >> ... 输入
    vector<int> nums(n);
    for (int i = 0; i < n; i++) {
        cin >> nums[i]; // 读取n个整数存入数组
    }
    Solution solution; // 创建一个Solution类型的对象(类似造一辆车!名字叫做solution)
    vector<int> result = solution.twoSum(nums, target);

    cout << result[0] << " " << result[1] << endl;
    return 0;
}

四、C++语法关键点解析

4.1 分号 ; 的使用规则(超详细总结)

4.1.1 必须加分号的情况
场景示例代码说明
语句末尾int a = 10; cout << "a";每个完整语句结束后必须加分号
单行控制流语句if (a>0) cout << "正数";单行if/while语句末尾加分号
类成员声明class A { int x; void f(); };成员变量和函数声明后加分号
枚举/联合体定义enum Color {RED, GREEN};定义末尾必须加分号
4.1.2 绝对不加分号的情况
场景错误代码正确代码说明
函数体结束 }void f() { ... };void f() { ... }函数体大括号后不加分号
预处理指令#include <iostream>;#include <iostream>#include等指令后不加分号
类定义结束 }class A { ... }class A { ... };唯一例外:类定义后必须加分号
大括号代码块内部if (a) { cout << "a"; ; }if (a) { cout << "a"; }大括号内语句末尾加分号,括号后不加
4.1.3 易混淆场景对比
// 正确:类定义后加分号
class Solution { 
    // 成员函数
}; 

// 错误:函数体后加分号
int main() { 
    // 代码块
}; // ❌ 多余分号

4.2 哈希表关键操作:find vs end

unordered_map<int, int> numToIndex;
if (numToIndex.find(complement) != numToIndex.end()) {
    // 找到补数,返回下标
}
  • find(key):在哈希表中查找键 key,若存在返回对应迭代器,否则返回 end()
  • end():返回一个指向哈希表“虚拟末尾”的迭代器,用于判断查找是否失败。
  • 类比:相当于在字典中查找单词,找到返回单词位置,找不到返回“字典最后一页的下一页”(不存在)。

五、常见错误与解决方案

5.1 C++编译错误:unordered_map 未声明

  • 原因:未启用C++11标准,或头文件缺失。
  • 解决方案
    1. 添加 #include <unordered_map>
    2. 编译时加参数 -std=c++11
      g++ code.cpp -o output -std=c++11
      

5.2 类定义末尾缺少分号

class Solution { 
    // 成员函数
} // ❌ 错误:缺少分号
  • 修正:在类定义结束的 } 后添加分号:
    class Solution { 
        // 成员函数
    }; // ✅ 正确
    

5.3 Python ACM输入错误:下标越界

  • 原因:输入格式错误,如未正确解析n和数组长度。
  • 解决方案:确保输入数据长度正确,如 nums = data[2: 2+n] 需与n匹配。

六、总结

6.1 算法优化对比

方法时间复杂度空间复杂度适用场景
暴力枚举O(n²)O(1)n很小的情况
哈希表O(n)O(n)大规模数据

6.2 学习建议

  1. C++语法:重点掌握分号规则、命名空间、STL容器(如vectorunordered_map)。
  2. 算法思维:学会用哈希表优化查找问题,理解空间换时间的思想。
  3. 代码习惯
    • 编译C++时默认启用C++11(-std=c++11)。
    • 用IDE(如VS Code)实时检查语法错误。

示例输入输出

  • 输入:nums = [2,7,11,15], target = 9
  • 输出:[0, 1]
  • 解释:2 + 7 = 9,下标分别为0和1。

作者:CodeIsLife
博客链接:https://blog.csdn.net/CodeIsLife
转载请注明出处
欢迎在评论区交流疑问,觉得有帮助可以点赞收藏~ 😊

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2397057.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【机器学习基础】机器学习入门核心算法:集成学习(Ensemble Learning)

机器学习入门核心算法&#xff1a;集成学习&#xff08;Ensemble Learning&#xff09; 1. 算法逻辑核心逻辑&#xff1a; 2. 算法原理与数学推导2.1 Bagging&#xff08;Bootstrap Aggregating&#xff09;2.2 Boosting2.3 Stacking 3. 模型评估评估指标基学习器选择策略 4. 应…

【TMS570LC4357】之相关驱动开发学习记录1

系列文章目录 【TMS570LC4357】之工程创建 【TMS570LC4357】之工程配置修改 【TMS570LC4357】之HALCOGEN使用 【TMS570LC4357】之相关问题及解决 ——————————————————— 前言 记录笔者在第一次使用TMS570过程中对外设驱动的一些学习碎片。 1. RTI 1.1 添…

RAG入门 - Retriever(1)

文章目录 环境准备知识库加载1. Retriever - embeddings &#x1f5c2;️1.1 将文档拆分为chunks1.2 词嵌入1.3 构建向量数据库Nearest Neighbor search algorithm &#xff08;最近邻搜索算法&#xff09;Distances &#xff08;距离&#xff09;点积&#xff08;Dot Product&…

pyspark实践

1。pyspark是什么 PySpark 是 Apache Spark 的官方 Python 接口&#xff0c;它使得 Python 开发者能够访问 Spark 的核心功能&#xff0c;如&#xff1a; Spark SQL&#xff1a;用于执行 SQL 查询以及读取数据的库&#xff0c;支持多种数据格式和存储系统。py.qizhen.xyz Data…

【深度学习新浪潮】多模态模型如何处理任意分辨率输入?

多模态模型处理任意分辨率输入的能力主要依赖于架构设计的灵活性和预处理技术的结合。以下是核心方法及技术细节: 一、图像模态的分辨率处理 1. 基于Transformer的可变补丁划分(ViT架构) 补丁化(Patch Embedding): 将图像分割为固定大小的补丁(如1616或3232像素),不…

K-匿名模型

K-匿名模型是隐私保护领域的一项基础技术&#xff0c;防止通过链接攻击从公开数据中重新识别特定个体。其核心思想是让每个个体在发布的数据中“隐匿于人群”&#xff0c;确保任意一条记录至少与其他K-1条记录在准标识符&#xff08;Quasi-Identifiers, QIDs&#xff09;上不可…

UE5蓝图暴露变量,在游戏运行时修改变量实时变化、看向目标跟随目标Find Look at Rotation、修改玩家自身弹簧臂

UE5蓝图中暴露变量&#xff0c;类似Unity中public一个变量&#xff0c;在游戏运行时修改变量实时变化 1&#xff0c;添加变量 2&#xff0c;设置变量的值 3&#xff0c;点开小眼睛&#xff0c;此变量显示在编辑器中&#xff0c;可以运行时修改 看向目标跟随目标Find Look at R…

Python-matplotlib中的Pyplot API和面向对象 API

matplotlib中的Pyplot API和面向对象 API Pyplot API&#xff08;状态机模式&#xff09;面向对象 API 详解二者差别核心区别方法命名差异注意事项差别举例 &#x1f345; Pyplot API&#xff08;状态机模式&#xff09;和面向对象 API 是两种不同的编程接口.&#x1f345; 它们…

FastAPI安全认证:从密码到令牌的魔法之旅

title: FastAPI安全认证:从密码到令牌的魔法之旅 date: 2025/06/02 13:24:43 updated: 2025/06/02 13:24:43 author: cmdragon excerpt: 在FastAPI中实现OAuth2密码流程的认证机制。通过创建令牌端点,用户可以使用用户名和密码获取JWT访问令牌。代码示例展示了如何使用Cry…

java对接bacnet ip协议(跨网段方式)

1、环境准备 #maven环境<repositories><repository><id>ias-releases</id><url>https://maven.mangoautomation.net/repository/ias-release/</url></repository></repositories><dependencies><dependency><…

LabVIEW超宽带紧凑场测量系统

采用 LabVIEW 开发超宽带紧凑场测量系统&#xff0c;实现天线方向图、目标雷达散射截面&#xff08;RCS&#xff09;及天线增益的自动化测量。通过品牌硬件设备&#xff0c;优化系统架构&#xff0c;解决传统测量系统在兼容性、数据处理效率及操作便捷性等方面的问题&#xff0…

编译rustdesk,使用flutter、hwcodec硬件编解码、支持Windows 7系统

目录 安装相应的环境安装visual studio安装vpkg安装rust开发环境安装llvm和clang编译源码下载源码使用Sciter作为UI的(已弃用)使用flutter作为UI的(主流)下载flutter sdk桥接静默安装支持Windows 7系统最近某desk免费的限制越来越多,实在没办法,平时远程控制用的比较多,…

ROS机器人和NPU的往事和新知-250602

往事&#xff1a; 回顾一篇五年前的博客&#xff1a; ROS2机器人笔记20-12-04_ros2 移植到vxworks-CSDN博客 里面提及专用的机器人处理器&#xff0c;那时候只有那么1-2款专用机器人处理器。 无关&#xff1a; 01&#xff1a; 每代人的智商和注意力差异是如何出现的-250602-…

【从零开始学习QT】信号和槽

目录 一、信号和槽概述 信号的本质 槽的本质 二、信号和槽的使用 2.1 连接信号和槽 2.2 查看内置信号和槽 2.3 通过 Qt Creator 生成信号槽代码 自定义槽函数 自定义信号 自定义信号和槽 2.4 带参数的信号和槽 三、信号与槽的连接方式 3.1 一对一 &#xff08;1&…

MCP调研

什么是 MCP MCP&#xff08;Model Context Protocol&#xff0c;模型上下文协议&#xff09;&#xff0c;是由 Anthropic 在 2024 年 11 月底推出的开放标准协议&#xff0c;旨在统一大型语言模型&#xff08;LLM&#xff09;与外部数据源、工具的通信方式。MCP 的主要目的在于…

TDengine 运维——巡检工具(定期检查)

背景 TDengine 在运行一段时间后需要针对运行环境和 TDengine 本身的运行状态进行定期巡检&#xff0c;本文档旨在说明如何使用巡检工具对 TDengine 的运行环境进行自动化检查。 安装工具使用方法 工具支持通过 help 参数查看支持的语法 Usage: taosinspect [OPTIONS]Check…

qwen 2.5 并行计算机制:依靠 PyTorch 和 Transformers 库的分布式能力

qwen 2.5 并行计算机制:依靠 PyTorch 和 Transformers 库的分布式能力 完整可运行代码: import torch import torch.nn.functional as F from transformers

MSTNet:用于糖尿病视网膜病变分类的多尺度空间感知 Transformer 与多实例学习方法|文献速递-深度学习医疗AI最新文献

Title 题目 MSTNet: Multi-scale spatial-aware transformer with multi-instance learning for diabetic retinopathy classification MSTNet&#xff1a;用于糖尿病视网膜病变分类的多尺度空间感知 Transformer 与多实例学习方法 01 文献速递介绍 糖尿病视网膜病变&#…

docker运行程序Killed异常排查

问题描述 我最近开发了一个C 多线程程序&#xff0c;测试没有问题&#xff0c;封装docker测试也没有问题&#xff0c;然后提交给客户了&#xff0c;然后在他那边测试有问题&#xff0c;不定时、不定位置异常中断&#xff0c;以前一直认为只要封装了docker就万事大吉&#xff0…

Excel 批量下载PDF、批量下载考勤图片——仙盟创梦IDE

在办公场景中&#xff0c;借助应用软件实现 Excel 批量处理考勤图片、电子文档与 PDF&#xff0c;具有诸多显著优势。 从考勤图片处理来看&#xff0c;通过 Excel 批量操作&#xff0c;能快速提取图片中的考勤信息&#xff0c;如员工打卡时间、面部识别数据等&#xff0c;节省…