LeetCode 第一题:两数之和(C 语言详解)
🌟 前言:为什么第一题也值得深挖?
LeetCode 的第 1 题「两数之和」看似简单,却是很多初学者在 C 语言环境下踩坑的“第一道坎”。尤其是当你看到 malloc、int*、*returnSize 这些关键词时,可能会一头雾水:
- 为什么必须用
malloc? - 为什么
ret是int*类型? - 为什么要写
*returnSize = 2?不写会怎样?
本文来搞懂这道题背后的内存机制和LeetCode 判题规则,让你不仅会做题的同时理解为什么这样写。
题目描述
给定一个整数数组nums和一个整数目标值target,请你在该数组中找出 和为目标值target的那 两个整数,并返回它们的数组下标。
你可以假设每种输入只会对应一个答案,并且你不能使用两次相同的元素。
你可以按任意顺序返回答案。
📌 本题默认函数参数说明
LeetCode 提供的 C 语言默认代码模板如下:
int* twoSum(int* nums, int numsSize, int target, int* returnSize)
*nums:用于求和的整数数组numsSize:传入数组的长度target:目标值*returnSize:用于返回结果数组的长度(若有解则为2,无解则为0)
✅ 参考代码实现
int* twoSum(int* nums, int numsSize, int target, int* returnSize) {
for (int i = 0; i < numsSize; ++i) {
// 固定 i,遍历 j,找到两个数相加等于 target
for (int j = i + 1; j < numsSize; ++j) {
if (nums[i] + nums[j] == target) {
// 找到两个相加等于 target 的数,分配内存,存储下标,返回
// sizeof(int):单个整数的字节大小
// * 2:分配 2 个整数的空间
int* ret = malloc(sizeof(int) * 2);
ret[0] = i;
ret[1] = j;
// 成功找到两个数之和为 target
*returnSize = 2;
// 返回找到的相应整数的下标
return ret;
}
}
}
// 遍历完数组,没有找到两个数之和为 target
*returnSize = 0;
// 没有找到,返回 NULL
return NULL;
}
❓ 新手常见疑问解析
🔹 为什么必须用 malloc?
栈内存 vs 堆内存
-
如果你写成:
int ret[2] = {i, j}; // 栈内存→ 函数返回后,
ret所在的栈帧被销毁,内存自动释放。
→ LeetCode 读取到的是野指针/随机值,程序可能崩溃或结果错误。 -
而
malloc在堆内存分配空间:int* ret = malloc(sizeof(int) * 2);→ 堆内存生命周期独立于函数调用,LeetCode 能安全读取返回的地址内容。
✅ 结论:必须用 malloc 保证返回的指针在函数结束后依然有效。
🔹 为什么 ret 是 int* 类型?
malloc返回的是void*(通用指针),在 C 语言中可隐式转换为其他指针类型。- 但为了代码清晰、类型安全,我们将其视为
int*,以便后续通过ret[0]、ret[1]存储整数下标。
💡 实际上在 C语言中不需要显式强制转换
(int*)malloc(...),但明确类型有助于理解。
🔹 *returnSize 有什么用?少了它会怎样?
作用
告诉调用者(LeetCode 判题系统)返回数组的长度。
为什么需要它?
- C 语言限制:函数无法直接返回数组长度(C 语言不支持返回数组)。
- 标准设计:通过 returnSize 指针间接传递长度,是 LeetCode 题目框架的强制要求。LeetCode 通过
returnSize这个输出参数来“知道”你返回了几个元素。
如果忘记设置?
-
LeetCode 会报错,例如:
returnSize not set -
即使你正确返回了下标,系统也无法知道结果数组长度,判题失败。
✅ 总结:
*returnSize = 2 或 *returnSize = 0 是 LeetCode 判题系统的“通信协议”。
这是代码中唯一不可省略的关键行——逻辑可以优化,但这一行必须保留!
🧠 小结
虽然「两数之和」是 LeetCode 第一题,逻辑简单,但在 C 语言中涉及多个底层细节:
- 堆内存分配(
malloc)确保返回数据有效 - 指针类型与内存管理的理解
- LeetCode 特有的输出参数
returnSize的作用
掌握这些细节,不仅能 AC 本题,更能为后续更复杂的 C 语言算法题打下坚实基础!
💬 提示:在实际工程中,调用方需负责
free()释放malloc分配的内存,但在 LeetCode 环境中无需手动释放。