Leetcode有几道相关的两数之和类的题目,在这里将题目总结如下。
1.#1 Two Sum 两数之和
1.1 原题目
Given an array of integers, return indices of the two numbers such that they add up to a specific target.
You may assume that each input would have exactly one solution, and you may not use the same element twice.
Example:
Given nums = [2, 7, 11, 15], target = 9,
Because nums[0] + nums[1] = 2 + 7 = 9,
return [0, 1].
1.2 解法
1.2.1、暴力迭代法
最初想到的方法是迭代法,从[0,n-1]
遍历数组,遍历至nums[i]
时,搜索nums[i+1,n-1]
满足条件的数字。代码如下,时间复杂度为O(n^2)
。
虽然能通过,但时间耗费很多。
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
vector<int> result;
for(int i=0;i<nums.size()-1;i++)
for(int j=i+1;j<nums.size();j++)
{
if(target==nums[i]+nums[j])
{
result.push_back(i);
result.push_back(j);
}
}
return result;
}
};
1.2.2、哈希表
待完善。对于哈希表的知识还不太熟悉。
2.#167 Two Sum II - Input array is sorted 两数之和之二 - 输入数组有序
2.1 原题目
Given an array of integers that is already sorted in ascending order, find two numbers such that they add up to a specific target number.
The function twoSum should return indices of the two numbers such that they add up to the target, where index1 must be less than index2.
Note:
Your returned answers (both index1 and index2) are not zero-based.
You may assume that each input would have exactly one solution and you may not use the same element twice.
Example:
Input: numbers = [2,7,11,15], target = 9
Output: [1,2]
Explanation: The sum of 2 and 7 is 9. Therefore index1 = 1, index2 = 2.
2.2 解法
这又是一道Two Sum的衍生题,作为LeetCode开山之题,我们务必要把Two Sum及其所有的衍生题都拿下,这道题其实应该更容易一些,因为给定的数组是有序的,而且题目中限定了一定会有解,我最开始想到的方法是二分法来搜索。
这道题目是LeetCode的数组和字符串章节的题目,涉及到双指针技巧,属于双指针的情景1。情景1的总结如下:
总之,使用双指针技巧的典型场景之一是你想要从两端向中间迭代数组。这时你可以使用双指针技巧:
一个指针从始端开始,而另一个指针从末端开始。
值得注意的是,这种技巧经常在数组排序
中使用。
2.2.1 二分法
自己做到这题的时候,第一个想法也是二分法(只不过当时还不知道这种方法叫二分法),该方法还没有使用到两端向中间迭代的双指针技巧。自己的代码如下,复杂度O(nlgn)
:
//O(nlgn)
class Solution {
public:
vector<int> twoSum(vector<int>& numbers, int target) {
int count=numbers.size();
if(count<=1)
return {};
bool find=false;
vector<int> res;
for(int i=0;i<count-1;i++)
{
int start=i+1;
int end=count-1;
while(start<=end&&find==false)
{
int center=(start+end)/2;
int tmp=numbers[i]+numbers[center];
if(tmp>target)
{
end=center-1;
}
else if(tmp<target)
{
start=center+1;
}
else
{
find=true;
res.push_back(i+1);
res.push_back(center+1);
}
}
if(find)
break;
}
return res;
}
};
2.2.2 双指针技巧(碰撞指针)
这种方法才使用到了双指针技巧,
总之,使用双指针技巧的典型场景之一是你想要从两端向中间迭代数组。这时你可以使用双指针技巧:
一个指针从始端开始,而另一个指针从末端开始。
值得注意的是,这种技巧经常在数组排序
中使用。
我们只需要两个指针,一个指向开头,一个指向末尾,然后向中间遍历,如果指向的两个数相加正好等于target
的话,直接返回两个指针的位置即可,若小于target
,左指针右移一位,若大于target
,右指针左移一位,以此类推直至两个指针相遇停止。代码如下,时间复杂度O(n)
。
// O(n)
class Solution {
public:
vector<int> twoSum(vector<int>& numbers, int target) {
int l = 0, r = numbers.size() - 1;
while (l < r) {
int sum = numbers[l] + numbers[r];
if (sum == target) return {l + 1, r + 1};
else if (sum < target) ++l;
else --r;
}
return {};
}
};
3.# Two Sum III - Data structure design 两数之和之三 - 数据结构设计
待完善,还未碰到此题。