【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⁹ ≤ nums[i] ≤ 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 nums[i] 补数 哈希表
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 语言题解专栏

相关推荐
老约家的可汗21 小时前
C++篇之类和对象下
java·开发语言·c++
Mr_WangAndy21 小时前
C++数据结构与算法_排序算法
c++·排序算法·基础排序·高级排序
niuniudengdeng21 小时前
六面独立转动魔方还原机器人设计与实现
数学·算法·机器人
ghie909021 小时前
基于MATLAB的A*算法避障路径规划实现
人工智能·算法·matlab
Irissgwe21 小时前
C&C++内存管理
c语言·开发语言·c++·c++内存管理
雾岛听蓝21 小时前
C文件操作与系统IO
linux·c语言·开发语言·经验分享·笔记·算法
zh路西法21 小时前
【宇树机器人强化学习】(一):PPO算法的python实现与解析
python·深度学习·算法·机器学习·机器人
随意起个昵称21 小时前
【贪心】选择尽量多的不相交区间
数据结构·算法
章小幽21 小时前
LeetCode-35.搜索插入位置
数据结构·算法·leetcode
放下华子我只抽RuiKe51 天前
机器学习全景指南-探索篇——发现数据内在结构的聚类算法
人工智能·深度学习·算法·机器学习·语言模型·数据挖掘·聚类