一、题目描述
输入一个递增排序的数组和一个数字s,在数组中查找两个数,使得它们的和正好是s。如果有多对数字的和等于s,则输出任意一对即可。
示例1:
输入:nums = [2,7,11,15], target = 9
输出:[2,7] 或者 [7,2]
示例2:
输入:nums = [10,26,30,31,47,60], target = 40
输出:[10,30] 或者 [30,10]
限制:
1
<
=
n
u
m
s
.
l
e
n
g
t
h
<
=
1
0
5
1 <= nums.length <= 10^5
1<=nums.length<=105
1
<
=
n
u
m
s
[
i
]
<
=
1
0
6
1 <= nums[i] <= 10^6
1<=nums[i]<=106
二、思路分析
注:思路分析中的一些内容和图片参考自力扣各位前辈的题解,感谢他们的无私奉献
思路
由于是递增数组,则可以考虑使用双指针,分别指向数组的前后两端。然后开始循环,每次循环判断两数之和与目标的大小关系来移动这两个指针。
算法流程:
①初始化:双指针 i i i、 j j j 分别指向数组 n u m s nums nums 的左右两端(俗称对撞双指针)
②循环搜索:当双指针相遇时跳出
----计算和 s = n u m s [ i ] + n u m s [ j ] s = nums[i] + nums[j] s=nums[i]+nums[j]
----若 s > t a r g e t s s > targets s>targets,则指针 j j j 向左移动,即执行 j = j − 1 j = j - 1 j=j−1
若 s < t a r g e t s s < targets s<targets,则指针 i i i 向右移动,即执行 i = i + 1 i = i + 1 i=i+1
若 s = t a r g e t s = target s=target,立即返回数组 [ n u m s [ i ] , n u m s [ j ] ] [nums[i], nums[j]] [nums[i],nums[j]]
③返回空数组,代表无和为 t a r g e t target target 的数字组合
案例分析:
复杂度分析:
时间复杂度 O ( N ) \rm{O(N)} O(N):N
为数组nums
的长度,双指针共同线性遍历整个数组
空间复杂度 O ( 1 ) \rm{O(1)} O(1):变量i
、j
使用常数大小的额外空间
三、整体代码
整体代码如下
/**
* Note: The returned array must be malloced, assume caller calls free().
*/
int* twoSum(int* nums, int numsSize, int target, int* returnSize){
int i = 0, j = numsSize - 1;
int* res = (int*)malloc(sizeof(int)*2);
while(i!=j){
if(nums[i]+nums[j] < target) i++;
else if (nums[i]+nums[j] > target) j--;
else break;
}
if(i != j){
res[0] = nums[i];
res[1] = nums[j];
*returnSize = 2;
return res;
}
else{
*returnSize = 0;
return NULL;
}
}
运行,测试通过