LeetCode/两数之和
给定一个整数数组nums和一个整数目标值target,请你在该数组中找出和为目标值target的那两个整数,并返回它们的数组下标
思路:求两数和等于目标值,首先考虑二重循环暴力求解,分别将每一个数与所有数进行求和匹配,时间复杂度为O(n2)。进一步可以考虑两求和数一个值大于目标值一半,一个值小于一半,可以分割成两部分进行匹配。若能使用C++容器模板,考虑使用哈希表hash_map进一步降低二重循环里匹配所需时间。
1. 暴力求解
双重循环
int* twoSum(int* nums, int numsSize, int target) {
int i,j;
int *result=NULL;
for(i=0;i
2. 哈希表优化
class Solution {
public:
vector twoSum(vector& nums, int target) {
map a;//提供一对一的hash
vector b(2,-1);//初始化一个大小为2,值为-1的数组,存放最终结果
for(int i=0;i0)//匹配的值存在哈希表中
{
b[0]=a[target-nums[i]];//获取匹配值的位置
b[1]=i; //存储另一值位置
break;
}
a[nums[i]]=i;//值为键来获取位置,维护扩大一个哈希表用于查询
}
return b;
};
};
3. 三数之和
先排序,即方便跳过相同的数,也便于双指针的移动,再使用双指针求两数之和
class Solution {
public:
vector> threeSum(vector& nums) {
int n = nums.size();
sort(nums.begin(), nums.end());
vector> ans;
// 先枚举 a ,再枚举b,这种遍历的结构注定不会重复,得到其组合数
for (int first = 0; first < n; ++first) {
// 需要和上一次枚举的数不相同
if (first > 0 && nums[first] == nums[first - 1]) //移动到不重复的位置
continue;
// c 对应的指针初始指向数组的最右端
int third = n - 1;
int target = -nums[first];//目标和,将问题转换为两数之和
// 枚举 b
for (int second = first + 1; second < n; ++second) {
// 需要和上一次枚举的数不相同
if (second > first + 1 && nums[second] == nums[second - 1])//移动到不重复位置
continue;
// 需要保证 b 的指针在 c 的指针的左侧,左右指针交替移动,这里移动右指针
while (second < third && nums[second] + nums[third] > target) //和大于目标值
--third; //移动右指针
if (second == third) break;//两指针会和遍历结束,其实循环用while的话不用加这句
if (nums[second] + nums[third] == target) {//找到目标值的话存入结果
ans.push_back({nums[first], nums[second], nums[third]});
}
}
}
return ans;
}
};