LeetCode刷算法题(C++)

1. 两数之和

cpp 复制代码
#include <vector>
#include <unordered_map>

using namespace std;

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        // 创建一个哈希表,用于存储 {数值, 下标}
        unordered_map<int, int> map;

        for (int i = 0; i < nums.size(); ++i) {
            // 计算当前数字需要的"另一半"
            int complement = target - nums[i];

            // 在哈希表中查找这"另一半"是否存在
            auto it = map.find(complement);

            if (it != map.end()) {
                // 如果找到了,返回两个数的下标
                // it->second 是之前存进去的那个数的下标
                // i 是当前数的下标
                return {it->second, i};
            }

            // 如果没找到,将当前数字和下标存入哈希表
            map[nums[i]] = i;
        }

        // 题目保证有解,理论上不会运行到这里
        return {};
    }
};

就是说防止6-3=3是吧

对,完全正确!你一下就抓住了最关键的核心! 防止 6 - 3 = 3 这种情况(也就是自己和自己配对),就是这种"边走边记"写法最妙的地方。

我们用你提到的 6 - 3 = 3 的例子,来看看如果强行把当前数字先存进去,会发生什么车祸现场:

❌ 假如我们"先存,再找"(也就是你想优化的逻辑)

假设 nums = [3, 4, 2],target = 6。

当循环走到第一个数 3(i = 0)时:

  1. 先存入: 你把 3 存进了哈希表,此时 map = {3: 0}。

  2. 再计算: complement = 6 - 3 = 3。

  3. 去查找: 它的另一半是 3,代码去哈希表里找 3。

  4. 结果: 找到了!因为你在第一步刚刚把它自己存进去。

  5. 报错返回: 代码兴奋地返回了 {0, 0}。

但这明显是错的,因为题目要求同一个数字不能用两次 ,你不能把下标为 0 的 3 既当左加数,又当右加数。

当前代码的"先找,找不到再存"

同样的例子,当前代码是这样见招拆招的:

当循环走到第一个数 3(i = 0)时:

  1. 先计算: complement = 6 - 3 = 3。

  2. 去查找: 它的另一半是 3,代码去哈希表里找 3。

  3. 结果: 找不到! 因为此时哈希表还是空的,当前的 3 还没来得及存进去呢!

  4. 存入备忘: 既然没找到,代码执行 map[3] = 0,把 3 存进去,留给以后的数字用。

你看,这样就完美错开了!它查找的永远是"过去出现过的历史数字",绝对不会和"自己当前这个数字"撞车。

所以,那个数字 7 没存进去,就是因为它在查找历史记录时,刚好和过去的 2 认亲成功了。既然家人们都找到了,它也就没必要再把自己登记到光棍榜(哈希表)上了,直接牵手成功退出程序!

1.2 - 找 4 和 2

没错,太聪明了!就是这个意思! 如果数组是 [3, 4, 2],目标值 target = 6:

  • 那个孤零零的 3 因为在前面找不到配对的 3,只能把自己存进哈希表,遗憾错过。

  • 紧接着,循环继续往后走,直到遇到 4 和 2。

我们顺着你的思路,看看代码是怎么把 4 和 2 揪出来的:

1. 走到数字 4(i = 1)

  • 算配对: complement = 6 - 4 = 2

  • 去查找: 它的另一半是 2。代码去哈希表里找 2。

  • 结果: 此时哈希表里只有之前存进去的 3({3: 0}),找不到 2。

  • 存备忘: 既然没找到,4 只能也把自己登记进去。

  • 此时哈希表内容: {3: 0, 4: 1}

2. 走到数字 2(i = 2)

  • 算配对: complement = 6 - 2 = 4

  • 去查找: 它的另一半是 4。代码去哈希表里找 4。

  • 结果: 哇,找到了! 因为上一步 4 刚刚把自己存进去。

  • 成功牵手: * 哈希表告诉我们,4 的下标是 1(it->second)。

    • 当前 2 的下标是 2(i)。
  • 返回结果: 直接执行 return {1, 2};,大功告成!

🎯 最后的终极闭环

你看,在这个过程中:

  1. 3 因为防范了6 - 3 = 3 的陷阱,安全地滑过去了。

  2. 4 没找到另一半,乖乖存了进去。

  3. 2 进来一找,刚好和已经存进去的 4 配对成功。

而这时候,数字 2 自己也同样没有机会存进哈希表 ,因为找到 4 的瞬间程序就 return 结束了。

你现在已经彻底把这个算法的底层逻辑、边界陷阱、还有为什么不存最后一个数的原因全部打通了!这其实就是大名鼎鼎的"一次遍历哈希法(One-pass Hash Table)",可以说是面试官最喜欢的标准满分答案。

相关推荐
晒太羊的猫12 分钟前
hot100动态规划刷题
算法·动态规划
weixin_5310946935 分钟前
heap_4内存管理
java·开发语言·算法
余额瞒着我当琳38 分钟前
红黑树的实现--红黑树的概念、规则、效率、结构、旋转、查找、验证
数据结构·c++·算法
程序员南飞42 分钟前
win系统安装minio
java·数据结构·算法
青少儿编程课堂44 分钟前
AC自动机多模式串匹配精讲:校园关键词巡检实战解析
c++·python·算法·bfs·信息学竞赛
longlongzihan1 小时前
LeetCode 5. 最长回文子串:从暴力匹配到中心扩展的思维演进
c++·算法·leetcode
waoooqwe1 小时前
问卷样本真实吗
大数据·数据库·算法·数据分析
苦瓜打怪兽2 小时前
leetcode 热题100(11. 盛最多水的容器)
python·算法·leetcode
多弗朗皮卡丘2 小时前
C++继承
c++·继承
汉克老师2 小时前
GESP2026年9月认证C++七级( 第三部分编程题(2、括号序列))精讲
c++·gesp·小学生·学c++编程