【LeetCode】1. 两数之和(Two Sum)— 哈希表经典题解(C语言)

一、题目描述

给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那两个整数,并返回它们的数组下标。

你可以假设每种输入 只会对应一个答案 ,并且 同一个元素不能使用两次。

可以按任意顺序返回答案。

示例 1

复制代码
输入: nums = [2,7,11,15], target = 9
输出: [0,1]
解释: nums[0] + nums[1] == 9

示例 2

复制代码
输入: nums = [3,2,4], target = 6
输出: [1,2]

示例 3

复制代码
输入: nums = [3,3], target = 6
输出: [0,1]

提示

  • 2 ≤ nums.length ≤ 10⁴

  • -10⁹ ≤ numsi ≤ 10⁹

  • -10⁹ ≤ target ≤ 10⁹

  • 只会存在一个有效答案


二、解题思路

这道题是 LeetCode 最经典的哈希表题目之一,也是很多面试的入门题。

常见解法有两种:

1️⃣ 暴力枚举

2️⃣ 哈希表优化(推荐)


三、方法一:暴力枚举

思路

最直接的方法就是 两层循环枚举所有组合:

  1. 第一个循环选择第一个数 nums[i]

  2. 第二个循环选择第二个数 nums[j]

  3. 判断:

    nums[i] + nums[j] == target

如果成立,则返回两个下标。


动图思路

假设数组:

复制代码
[2,7,11,15]

target = 9

枚举过程:

复制代码
2 + 7  = 9  ✔

返回:

复制代码
[0,1]

C语言代码

复制代码
#include <stdlib.h>

int* twoSum(int* nums, int numsSize, int target, int* returnSize) {

    int* res = (int*)malloc(sizeof(int) * 2);

    for(int i = 0; i < numsSize; i++)
    {
        for(int j = i + 1; j < numsSize; j++)
        {
            if(nums[i] + nums[j] == target)
            {
                res[0] = i;
                res[1] = j;
                *returnSize = 2;
                return res;
            }
        }
    }

    *returnSize = 0;
    return NULL;
}

复杂度分析

复杂度 数值
时间复杂度 O(n²)
空间复杂度 O(1)

当数组较大时,效率会明显下降。


四、方法二:哈希表(推荐)⭐

核心思想

如果:

复制代码
a + b = target

那么:

复制代码
b = target - a

遍历数组时:

  1. 计算当前数需要的 补数

    complement = target - nums[i]

  2. 查询哈希表中是否存在该补数

  • 如果存在 → 找到答案

  • 如果不存在 → 将当前数字存入哈希表

这样只需要 遍历一次数组。


执行过程示例

数组:

复制代码
[2,7,11,15]

target = 9

遍历过程:

i numsi 补数 哈希表
0 2 7 存入2
1 7 2 找到2 ✔

返回:

复制代码
[0,1]

五、C语言实现(哈希表)

由于 C 语言没有内置哈希表,我们可以用 链地址法实现简单哈希表。

复制代码
#include <stdlib.h>

#define SIZE 20011

typedef struct Node
{
    int key;
    int value;
    struct Node* next;
}Node;

Node* hashTable[SIZE];

int hash(int key)
{
    if(key < 0) key = -key;
    return key % SIZE;
}

void insert(int key, int value)
{
    int h = hash(key);

    Node* node = (Node*)malloc(sizeof(Node));
    node->key = key;
    node->value = value;
    node->next = hashTable[h];

    hashTable[h] = node;
}

int find(int key)
{
    int h = hash(key);

    Node* cur = hashTable[h];

    while(cur)
    {
        if(cur->key == key)
            return cur->value;

        cur = cur->next;
    }

    return -1;
}

int* twoSum(int* nums, int numsSize, int target, int* returnSize)
{
    for(int i = 0; i < SIZE; i++)
        hashTable[i] = NULL;

    int* res = (int*)malloc(sizeof(int) * 2);

    for(int i = 0; i < numsSize; i++)
    {
        int complement = target - nums[i];

        int index = find(complement);

        if(index != -1)
        {
            res[0] = index;
            res[1] = i;
            *returnSize = 2;
            return res;
        }

        insert(nums[i], i);
    }

    *returnSize = 0;
    return NULL;
}

六、复杂度分析

复杂度 数值
时间复杂度 O(n)
空间复杂度 O(n)

因为只遍历了一次数组,所以效率非常高。


七、总结

方法 时间复杂度 空间复杂度
暴力枚举 O(n²) O(1)
哈希表 O(n) O(n)

在实际面试中,哈希表解法是最推荐的方案。

核心思想可以总结为一句话:

在遍历数组时,利用哈希表快速查找当前数字所需要的补数。


八、延伸题目

Two Sum 是很多题目的基础,例如:

    1. 三数之和(Three Sum)
    1. 四数之和(Four Sum)
    1. 两数之和 II(有序数组)

掌握 Two Sum 的 哈希表思想,可以帮助解决很多类似问题。


如果这篇文章对你有帮助,欢迎 点赞 + 收藏 + 关注 ⭐

后续会持续更新 LeetCode 面试经典 150 题 C 语言题解专栏。

相关推荐
the3clipse5 小时前
H.265熵编码核心:CABAC自适应二进制算术编码详解——如何将语法元素高效压缩为比特流
人工智能·算法·视频编码·h.265·hevc·cabac·cavlc
CQU_JIAKE5 小时前
10.4【A】
算法
Godspeed Zhao5 小时前
现代智能雷达技术19——算法(5)
算法
(Charon)5 小时前
【C++面试】RAII到底是什么:从资源管理理解C++对象生命周期
c++·算法·面试
无名猿5 小时前
成员初始化列表与初始化顺序陷阱:按声明顺序,不是书写顺序
c++·现代c++·语法基础
Omics Pro5 小时前
之江实验室NAR|虚拟细胞3阶段训练范式
数据库·人工智能·算法·机器学习·自然语言处理
Tisfy5 小时前
LeetCode 0678.有效的括号字符串:O(n)+O(1)一次遍历
算法·leetcode·字符串·题解·贪心·括号匹配
91刘仁德5 小时前
传输层协议深度拆解:端口寻址、UDP 报文与 TCP 可靠性机制全解析
linux·网络·c++·网络协议·tcp/ip·udp·c
小O的算法实验室5 小时前
IEEE TEVC,学习辅助的搜索路径重构进化算法
学习·算法·重构
Liuchang09115 小时前
洛谷 P2670 [NOIP 2015 普及组] 扫雷游戏
c++·算法·游戏