LeetCode/两数之和
给定一个整数数组nums和一个整数目标值target,请你在该数组中找出和为目标值target的那两个整数,并返回它们的数组下标
思路:求两数和等于目标值,首先考虑二重循环暴力求解,分别将每一个数与所有数进行求和匹配,时间复杂度为O(n2)。进一步可以考虑两求和数一个值大于目标值一半,一个值小于一半,可以分割成两部分进行匹配。若能使用C++容器模板,考虑使用哈希表hash_map进一步降低二重循环里匹配所需时间。
1. 暴力求解
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
for(int i=0;i<nums.size();i++)
for(int j=i+1;j<nums.size();j++)
if(nums[i]+nums[j]==target) return {i,j};
return {};
}
};
2. 哈希表优化
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
map<int,int> m;//建立值和索引哈希表
for(int i=0;i<nums.size();i++)//从前往后遍历,哈希表的扩大,以及查询匹配值
{
if(m.find(target-nums[i])!=m.end())//匹配的值存在哈希表中
return {m[target-nums[i]],i};
m[nums[i]]=i;//值为键来获取位置,维护扩大一个哈希表用于查询
}
return {};
};
};
3. 三数之和
先排序,即方便跳过相同的数,也便于双指针的移动,再使用双指针求两数之和
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
int n = nums.size();
sort(nums.begin(), nums.end());
vector<vector<int>> 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;
}
};
4. 四数之和
class Solution {
public:
vector<vector<int>> fourSum(vector<int>& nums, int target) {
int n =nums.size();
if(n<4) return {};
sort(nums.begin(),nums.end());
vector<vector<int>> res;
long sum;//求和值
for(int first =0;first<=n-4;first++){//首指针循环
if(first>0&&nums[first]==nums[first-1]) continue;//跳过重复元素
for(int second = first + 1;second <= n-3; second++){
if(second>first+1&&nums[second]==nums[second-1]) continue;//跳过重复元素
int third = second+1;
int fouth = n-1;
while(third<fouth){//最后一重双指针循环
sum = (long)nums[first]+nums[second]+nums[third]+nums[fouth];
if(sum==target){
res.push_back({nums[first],nums[second],nums[third],nums[fouth]});
while(nums[third+1]==nums[third]&&third+1<fouth) third++;
while(nums[fouth-1]==nums[fouth]&&third<fouth-1) fouth--;
third++;//这里进行扰动,先移动左右指针都可以
}
else if(sum<target) third++;
else if(sum>target) fouth--;
}
}
}
return res;
}
};

浙公网安备 33010602011771号