思路:
细节:都需要排序! 排序! 排序!
1.两数之和
1.1思路:使用无序的map,键存nums[i], 值存i, 循环遍历数组Nums,使用map.find(target - nums[i])查找是否存在,存在则返回两个下标i, iter->second,不存在则使用insert函数添加入map中
1.2实现细节: 使用到映射map, 迭代器auto = map.find(), map.insert(pair<int,int>{nums1, nums2}),需要注意最后找不到的话返回一个空vector, 可以使用空{}。
2.三数之和
2.1思路: 使用双指针的方法把O(n3)的时间复杂度减到O(n2),共两层循环, 难点是去重与剪枝,特别是第二个循环的去重和剪枝,第一层循环从nums[0],到nums.size(),第二层循环是right > left, i的去重放在前面, 但是left和right的去重需要在找到第一个成立的数组后进行,原因在于放前面会漏掉例如0, 0 ,0 的情况
2.2实现细节: i剪枝:i > 0 && nums[i] > target break; left right去重: while(right > left && nums[left] == nums[left+ 1])。注意找到第一个结果后为其去重时判断条件加上right > left, 这是前提。
3.四数之和
3.1思路: 在三数之和的基础上加一层循环,k, i, left, right,难点在于四个参数的剪枝和去重, 同样left和right的去重需要放在找到第一个答案之后进行
3.2实现细节:i的剪枝 nums[k] + nums[i] > target && nums[k] + nuns[i] >= 0 break; while(right > left)里的判断, if((long long)target - nums[k] - nums[i] < nums[left] + nums[right]), 这里需要使用long long的数据类型; target需要采用long long数据类型
两数之和
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
//使用哈希表
unordered_map<int,int> map;
for(int i = 0; i < nums.size(); i++){
auto it = map.find(target - nums[i]); //使用auto类型
if(it != map.end()){ //如果没找到就会返回一个尾后迭代器
return {it->second, i}; //返回多个值需要用大括号{}
}
else{
map.insert(pair<int,int>(nums[i], i));
}
}
return {};//这里只是完成格式
}
};
三数之和
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
vector<vector<int>> result; //定义了一个二维数组,用于存放每一个三元组()结果
sort(nums.begin(), nums.end());
//a = nums[i], b = nums[left], c = nums[left]
for(int i = 0; i < nums.size(); i++){
//排序后,只要一个数大于0就不再满足要求
if(nums[i] > 0){
return result;
}
//第一个去重,去重i, 注意这里是与i - 1做对比,不能与i + 1做对比, i+ 1对应left
if(i > 0 && nums[i] == nums[i - 1]){
continue;
}
int left = i + 1;
int right = nums.size() - 1;
while(right > left){ //最外层循环
if(nums[i] + nums[left] + nums[right] > 0)
{right--;
while(left < right && nums[right] == nums[right + 1]) right--;
}
else if(nums[i] + nums[left] + nums[right] < 0){
left++;
while(left < right && nums[left] == nums[left - 1]) left++;
}else{
result.push_back(vector<int>{nums[i], nums[left], nums[right]});
//去重逻辑应该放在找到一个三元组之后
while(right > left && nums[right] == nums[right - 1]) right--;
while(right > left && nums[left] == nums[left + 1]) left++;
//找到答案,同时缩减
right--;
left++;
}
}
}
return result;
}
};
四数之和
class Solution {
public:
vector<vector<int>> fourSum(vector<int>& nums, int target) {
vector<vector<int>> result; //存储二维数组
sort(nums.begin(), nums.end());//排序
for(int k = 0; k < nums.size(); k++){ //第一层循环
if(nums[k] > target && nums[k] >= 0){//剪枝
break;
}
if(k > 0 && nums[k] == nums[k-1]) continue;//去重
for(int i = k+1; i < nums.size(); i++){
if(nums[k] + nums[i] > target && nums[k] + nums[i] >= 0){//剪枝
break;
}
if(i > k + 1 && nums[i] == nums[i-1]) continue;//去重
long left = i + 1; //左指针
long right = nums.size() - 1;//右指针
while(right > left){
if((long long)target - nums[k] - nums[i] < long(nums[left] + nums[right])){right--; //注意是left++ 还是right--
}
else if((long long)target - nums[k] - nums[i] > long(nums[left] + nums[right])){
left++;
}
else{
result.push_back(vector<int>{nums[k], nums[i], nums[left], nums[right]});
while(right > left && nums[right] == nums[right - 1]) right--; //right去重
while(right > left && nums[left] == nums[left + 1]) left++; //left去重
right--; //收缩
left++;
}
}
}
}
return result;
}
};