LeetCode Hot 100——1.两数之和
1. 两数之和
题目
给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出和为目标值 target 的那两个整数,并返回它们的数组下标。
你可以假设每种输入只会对应一个答案,并且你不能使用两次相同的元素。
你可以按任意顺序返回答案。
示例 1:
输入: nums = [2,7,11,15], target = 9
输出: [0,1]
解释: 因为 nums[0] + nums[1] == 9,返回 [0, 1]。
示例 2:
输入: nums = [3,2,4], target = 6
输出: [1,2]
示例 3:
输入: nums = [3,3], target = 6
输出: [0,1]
提示
2 <= nums.length <= 10^4-10^9 <= nums[i] <= 10^9-10^9 <= target <= 10^9- 只会存在一个有效答案。
进阶
你可以想出一个时间复杂度小于 $O(n^2)$ 的算法吗?
解法
解法一:暴力遍历
两层循环遍历所有数对,检查是否满足 nums[i] + nums[j] == target。时间复杂度 $O(n^2)$,空间复杂度 $O(1)$。
使用 static 数组
/**
* Note: The returned array must be malloced, assume caller calls free().
*/
int* twoSum(int* nums, int numsSize, int target, int* returnSize) {
static int returned[2] = {0};
for (int i = 0; i < numsSize - 1; i++) {
for (int j = i + 1; j < numsSize; j++) {
if (nums[i] + nums[j] == target) {
returned[0] = i;
returned[1] = j;
*returnSize = 2;
return returned;
}
}
}
return NULL;
}
为什么使用 static?
C 语言中,函数的局部变量存储在栈上,函数返回后栈空间会被回收。如果直接返回指向局部数组的指针,调用方将得到一个悬垂指针,访问它会导致未定义行为。
使用 static 修饰数组后,数组具有静态存储期,生命周期贯穿整个程序运行,函数返回后仍然可以安全访问。
⚠️ 注意:
static方式并非线程安全,且多次调用会覆盖上一次的结果。
returnSize 存在的意义?
LeetCode 的 C 语言接口返回类型为 int*(指针),仅凭指针无法得知返回数组的长度。因此通过输出参数 returnSize 来告知调用者数组的实际元素个数(此处为 2)。这是 C 语言中返回动态大小数据的常见模式。
使用 malloc 分配堆区内存
/**
* Note: The returned array must be malloced, assume caller calls free().
*/
int* twoSum(int* nums, int numsSize, int target, int* returnSize) {
// static int returned[2] = {0}; // 对比上方 static 版本
int* returned = (int*)malloc(sizeof(int) * 2);
for (int i = 0; i < numsSize - 1; i++) {
for (int j = i + 1; j < numsSize; j++) {
if (nums[i] + nums[j] == target) {
returned[0] = i;
returned[1] = j;
*returnSize = 2;
return returned;
}
}
}
// free(returned);
return NULL;
}
⚠️ 注意:使用
malloc需包含头文件<stdlib.h>。若遍历结束未找到答案,应free释放已分配的内存,避免内存泄漏(但是题目前的提示说了,假设调用者会释放内存,所以此处可以不用写free函数)。
指针的数组写法
在 C 语言中,returned[0] 等价于 *(returned + 0),returned[1] 等价于 *(returned + 1)。数组下标运算本质是指针运算的语法:a[i] 会被编译器解释为 *(a + i),指针加法会自动根据元素类型进行缩放(int 类型每次偏移 sizeof(int) 字节)。因此,无论是 static 数组还是 malloc 分配的堆内存,都可以用 [] 进行下标访问。
解法二:哈希表
还没学习,后续更新
使用哈希表可以将查找时间从 $O(n)$ 降低到 $O(1)$,从而将整体时间复杂度优化到 $O(n)$。

浙公网安备 33010602011771号