[LeetCode] Sum of Two Integers 两数之和

本文介绍了一种不使用+/-运算符计算两个整数之和的方法。通过异或计算不考虑进位的和,通过与操作及左移计算进位,并递归或迭代地完成整个加法过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

Calculate the sum of two integers a and b, but you are not allowed to use the operator + and -.

Example:
Given a = 1 and b = 2, return 3.

Credits:
Special thanks to @fujiaozhu for adding this problem and creating all test cases.

 

这道题是CareerCup上的一道原题,难道现在LeetCode的新题都是到处抄来的么,讲解可以参见我之前的博客18.1 Add Two Numbers。简而言之就是用异或算不带进位的和,用与并左移1位来算进位,然后把两者加起来即可,先来看递归的写法如下:

 

解法一:

class Solution {
public:
    int getSum(int a, int b) {
        if (b == 0) return a;
        int sum = a ^ b;
        int carry = (a & b) << 1;
        return getSum(sum, carry);
    }
};

 

上面的解法可以精简到一行,哈哈,叼不叼?

 

解法二:

class Solution {
public:
    int getSum(int a, int b) {
        return b == 0 ? a : getSum(a ^ b, (a & b) << 1);
    }
};

 

也可以写成迭代的样子,思路都是一样的~

 

解法三:

class Solution {
public:
    int getSum(int a, int b) {
        while (b) {
            int carry = (a & b) << 1;
            a = a ^ b;
            b = carry;
        }
        return a;
    }
};

 

参考资料:

http://www.cnblogs.com/grandyang/p/5451942.html

https://leetcode.com/discuss/111682/one-line-java-code

https://leetcode.com/discuss/111601/6-line-java-solution

 

LeetCode All in One 题目讲解汇总(持续更新中...)

<think>我们正在处理用户关于LeetCode上"两数之和"问题的C语言实现请求。根据用户提供的引用内容,我们可以整合多个来源的C语言实现代码,并给出一个标准且正确的版本。 用户引用的几个来源都提供了C语言实现,但存在一些差异和潜在问题。我们需要: 1. 确保代码符合题目要求(返回两个数的下标,使得它们的和等于目标值) 2. 注意内存分配(题目要求返回的数组必须是malloc分配的) 3. 避免重复使用同一个元素 4. 优化循环(避免不必要的重复计算) 参考引用[2]和[4]中的代码,我们发现: - 引用[2]中的代码使用两层循环,但内层循环从0开始,这样会导致同一个元素被使用两次(虽然加了i!=j的判断,但效率较低,且返回的下标顺序可能不符合预期) - 引用[4]中的代码内层循环从index1+1开始,这样避免了重复使用同一个元素,也避免了i和j相同的情况,同时减少了循环次数。 因此,我们将以引用[4]的代码为基础,并参考引用[2]和引用[3]进行修正。 标准实现: 题目要求:给定一个整数数组和一个目标值,返回两个数的下标(从0开始),使得它们的和等于目标值。假设每个输入只对应一个答案,且不能重复使用同一个元素。 注意:LeetCode的题目要求返回的下标是从0开始还是从1开始?根据引用[4]的代码,它返回的是index1+1和index2+1(即从1开始),但题目描述中并没有明确要求从1开始。实际上,LeetCodeTwo Sum问题通常返回从0开始的下标。我们查看引用[2]和[3]的代码,返回的都是从0开始的下标。 因此,我们应返回从0开始的下标。 另外,引用[4]的代码中,返回的下标是index1+1和index2+1,这可能是题目要求返回非零下标(如题目要求返回的是第几个元素,即从1开始),但LeetCode原题描述中明确要求返回的是从0开始的下标。所以我们需要调整。 根据LeetCode官方题目描述(Two Sum): "Given an array of integers nums and an integer target, return indices of the two numbers such that they add up to target." 因此,我们返回的下标应该是从0开始的。 综合以上,我们给出以下C语言实现: 步骤: 1. 检查输入数组是否为空,以及数组大小是否小于2,如果是则返回NULL。 2. 使用两层循环,外层循环从0到n-2,内层循环从外层当前索引的下一个位置开始到n-1。 3. 在内层循环中检查两数之和是否等于目标值,如果相等,则分配一个包含两个整数的数组,将两个索引存入,并返回该数组。 4. 如果没有找到,则返回NULL(但题目保证有且只有一个答案,所以这一步也可以不处理,但为了安全还是返回NULL)。 5. 注意:在LeetCode上提交时,主函数不需要写,只需要写出twoSum函数即可。但为了用户测试,我们可以提供一个测试用的主函数。 代码实现: ```c #include <stdio.h> #include <stdlib.h> int* twoSum(int* nums, int numsSize, int target) { // 检查输入 if (nums == NULL || numsSize < 2) { return NULL; } // 使用两层循环 for (int i = 0; i < numsSize - 1; i++) { for (int j = i + 1; j < numsSize; j++) { if (nums[i] + nums[j] == target) { int* result = (int*)malloc(2 * sizeof(int)); if (result == NULL) { return NULL; // 内存分配失败 } result[0] = i; result[1] = j; return result; } } } return NULL; // 没有找到答案 } // 测试用主函数 int main() { int nums[] = {2, 7, 11, 15}; int target = 9; int numsSize = sizeof(nums) / sizeof(nums[0]); int* result = twoSum(nums, numsSize, target); if (result != NULL) { printf("[%d, %d]\n", result[0], result[1]); free(result); // 释放内存 } else { printf("No solution found.\n"); } return 0; } ``` 说明: 1. 该代码使用了两层循环,时间复杂度为$O(n^2)$,空间复杂度为$O(1)$(不考虑返回数组的内存分配)。 2. 在找到答案后立即返回,不会继续循环。 3. 在main函数中,我们提供了一个测试用例,并打印结果,注意释放分配的内存。 注意:在实际提交到LeetCode时,只需要提交twoSum函数部分,不需要提交main函数。 关于引用[2]中提到的在VC6.0上运行成功但在LeetCode上报错的问题,可能是因为LeetCode的编译器对C语言的语法要求更严格(比如变量声明必须在函数开头,或者C99标准等)。我们的代码使用了C99标准的循环变量声明(for循环内定义int i, j),LeetCode支持C99,所以没有问题。但如果使用旧标准,可以将循环变量定义在函数开头。这里我们按照C99标准编写。 另外,引用[2]的代码中,内层循环也是从0开始,然后通过i!=j来避免同一个元素,但这样会导致效率降低(多循环了很多次),而且返回的下标顺序可能是[j, i](因为先赋值indice[1]=i,然后indice[0]=j)。而我们的代码中,内层循环从i+1开始,避免了重复,并且返回的顺序是[i, j]。 最后,我们生成相关问题: §§相关问题§§ 1. 如何优化两数之和问题的解法,使其时间复杂度低于$O(n^2)$? 2. 两数之和问题中,如果数组是有序的,是否有更优的解法? 3. 两数之和问题在现实中有哪些应用场景?</think>### LeetCode "两数之和"问题 C语言实现 题目要求:给定一个整数数组 `nums` 和一个目标值 `target`,在数组中找出**和为目标值**的两个整数,并返回它们的数组下标(从0开始)。假设每个输入只对应唯一答案,且同一元素不能使用两次。 #### 标准C语言实现代码: ```c #include <stdio.h> #include <stdlib.h> int* twoSum(int* nums, int numsSize, int target) { // 输入有效性检查 if (nums == NULL || numsSize < 2) return NULL; // 动态分配结果数组内存 int* result = (int*)malloc(2 * sizeof(int)); if (result == NULL) return NULL; // 双重循环查找匹配 for (int i = 0; i < numsSize - 1; i++) { for (int j = i + 1; j < numsSize; j++) { if (nums[i] + nums[j] == target) { result[0] = i; // 存储第一个下标 result[1] = j; // 存储第二个下标 return result; // 返回结果 } } } free(result); // 未找到时释放内存 return NULL; // 未找到匹配项 } // 测试用例 int main() { int nums[] = {2, 7, 11, 15}; int target = 9; int numsSize = sizeof(nums) / sizeof(nums[0]); int* indices = twoSum(nums, numsSize, target); if (indices != NULL) { printf("下标: [%d, %d]\n", indices[0], indices[1]); free(indices); // 必须释放分配的内存 } else { printf("未找到匹配\n"); } return 0; } ``` #### 关键点解析: 1. **内存管理** 使用 `malloc` 动态分配返回数组的内存,调用者需负责调用 `free()` 释放内存[^2][^4]。 2. **算法逻辑** - 双重循环遍历所有元素组合 - 外层循环从 $i=0$ 到 $n-2$ - 内层循环从 $j=i+1$ 到 $n-1$,避免重复使用元素 - 时间复杂度:$O(n^2)$,空间复杂度:$O(1)$ 3. **边界处理** - 检查输入数组是否为空 - 处理数组长度小于2的情况 - 确保不访问越界内存 4. **测试用例输出** ``` 输入: [2,7,11,15], target=9 输出: 下标: [0, 1] ``` 验证:$2 + 7 = 9$,对应下标0和1。 #### 常见错误修正: - **错误1**:内层循环从0开始(导致重复使用元素) **修正**:内层循环从 `j = i + 1` 开始[^4] - **错误2**:未检查内存分配失败 **修正**:添加 `if (result == NULL) return NULL;` - **错误3**:返回局部变量指针 **修正**:必须使用 `malloc` 分配返回数组[^2]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值