代码训练LeetCode(37)两数之和

代码训练(37)两数之和

Author: Once Day Date: 2025年6月22日

漫漫长路,才刚刚开始…

全系列文章可参考专栏: 十年代码训练_Once-Day的博客-CSDN博客

参考文章:

1. 原题

给你一个下标从 1 开始的整数数组 numbers ,该数组已按 非递减顺序排列 ,请你从数组中找出满足相加之和等于目标数 target 的两个数。如果设这两个数分别是 numbers[index1]numbers[index2] ,则 1 <= index1 < index2 <= numbers.length

以长度为 2 的整数数组 [index1, index2] 的形式返回这两个整数的下标 index1index2

你可以假设每个输入 只对应唯一的答案 ,而且你 不可以 重复使用相同的元素。

你所设计的解决方案必须只使用常量级的额外空间。

提示:

  • 2 <= numbers.length <= 3 * 104
  • -1000 <= numbers[i] <= 1000
  • numbers非递减顺序 排列
  • -1000 <= target <= 1000
  • 仅存在一个有效答案

示例 1:

输入:numbers = [2,7,11,15], target = 9
输出:[1,2]
解释:2 与 7 之和等于目标数 9 。因此 index1 = 1, index2 = 2 。返回 [1, 2] 。

示例 2:

输入:numbers = [2,3,4], target = 6
输出:[1,3]
解释:2 与 4 之和等于目标数 6 。因此 index1 = 1, index2 = 3 。返回 [1, 3] 。
2. 分析

给定一个已经按非递减顺序排列的整数数组 numbers,我们需要找到两个数,它们的和正好等于给定的目标数 target。返回这两个数的下标(从1开始计数),确保第一个下标小于第二个下标。题目保证有唯一解,并且不允许重复使用相同的元素。

由于数组已经是排序过的,我们可以利用双指针技术来解决这个问题。具体步骤如下:

  1. 初始化两个指针left 指向数组的开始(下标 1),right 指向数组的结束(下标 numbers.length)。

  2. 遍历数组

    :通过循环移动两个指针来寻找两个数:

    • 如果 numbers[left] + numbers[right] 等于 target,则找到了正确的组合。
    • 如果和小于 target,由于数组是非递减的,为了增加和的值,向右移动 left 指针。
    • 如果和大于 target,为了减少和的值,向左移动 right 指针。
  3. 返回结果:当找到符合条件的两个数时,返回它们的下标。

例如,对于输入 numbers = [2, 3, 4]target = 6

  • 初始化 left = 1right = 3
  • 计算和 2 + 4 = 6,这恰好等于目标值 6
  • 返回 [1, 3]

性能优化关键点

  • 空间复杂度:由于使用的是双指针技术,除了返回结果外,没有使用额外的数据结构,因此空间复杂度为 O(1)。
  • 时间复杂度:双指针遍历一次数组,时间复杂度为 O(n)。
3. 代码实现
#include <stdio.h>

int* twoSum(int* numbers, int numbersSize, int target, int* returnSize) {
    int left = 0;
    int right = numbersSize - 1;
    *returnSize = 2;
    int* result = (int*)malloc(2 * sizeof(int));  // 动态分配返回数组

    while (left < right) {
        int sum = numbers[left] + numbers[right];
        if (sum == target) {
            result[0] = left + 1;  // 返回的下标从1开始
            result[1] = right + 1;
            return result;
        } else if (sum < target) {
            left++;
        } else {
            right--;
        }
    }
    return result;  // 此处返回是为了避免编译警告,实际上题目保证有解
}

int main() {
    int numbers[] = {2, 3, 4};
    int target = 6;
    int returnSize;
    int* indices = twoSum(numbers, sizeof(numbers) / sizeof(numbers[0]), target, &returnSize);
    
    printf("[%d, %d]\n", indices[0], indices[1]);
    free(indices);  // 释放动态分配的内存
    return 0;
}
4. 总结

这个题目考察了对排序数组的双指针技巧的应用,对于非递减数组中的两数之和问题,双指针方法非常高效。通过这类问题的练习,可以加深对数组操作和双指针技巧的理解和掌握。为了进一步提升编程能力,建议练习更多使用双指针解决的问题,如三数之和、最接近的三数之和等。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值