leetcode 2数/3数/4数之和

描述

2数之和

给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。

你可以假设每种输入只会对应一个答案。但是,你不能重复利用这个数组中同样的元素。

分析

  • 不能重复利用相同的元素,那么需要对输入数组nums 排序,或者使用set来去重,本题中要求返回数组下标,则不能sort
  • 简单的暴力求解: 2层循环,和target比较
  • 左右指针,left 从左逼近,right从右逼近,线性时间复杂度,可以用来求解 具体的解集合,但是由于排序破坏了下标,故而无法使用
  • 使用map来记录nums[index]需要的值和index
    • 对于nums[i]的数,它需要的值是target - nums[i];
    • 首先在map中查询是否有需要nums[i],如果有,则使用第一个作为解(为了去重而不继续使用其他的)
    • 如果不在,把nums[i]需要的值注册进入map等待配对

算法

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        vector<int> result;
        vector<int> tmp;
        unordered_multimap<int,int> hash;
        for(int i =0;i < nums.size(); ++i){
           if(hash.count(nums[i]) != 0){
               auto it = hash.equal_range(nums[i]);
               result.push_back(i);
               result.push_back(it.first->second);
               break;
           }else{
               hash.emplace(target-nums[i],i);
           }
        }
        return result;
    }
};

3数之和

给定一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?找出所有满足条件且不重复的三元组。

注意:答案中不可以包含重复的三元组。

分析

  • 不重复且直接要求解集合,用sort升序列排列nums
  • 对于 a + b + c = target 的题,可以变成 a + b = target -c ,用一个循环来遍历c,则在每次循环内部,target - c都是固定的,就变成在循环内部求解2数之和
  • 需要适当的减枝(当c > target时,由于升序,不可能再有解,直接退出)
  • 去重分2层,第一层c 去重,使用确保在c循环时,使用的数字都不同
  • 第二层去重在循环内部求解2数之和

算法

class Solution {
public:
    vector<vector<int>> threeSum(vector<int>& nums) {
        vector<vector<int>> result;
        if(nums.size() < 3) return result;
        sort(nums.begin(),nums.end());
        int target = 0;
        for(int i = 0; i < nums.size() -1;++i){
        	// 减枝
            if(nums[i] > target){
                break;
            }
            //第一层c 去重,使用确保在c循环时,使用的数字都不同
            if(i > 0 && nums[i] == nums[i -1]) continue;
            int l = i + 1,r = nums.size() -1;
            int t = target - nums[i];
            while(l < r){
                int sum = nums[l] + nums[r]; 
                if(sum == t){
                    result.push_back(vector<int>{nums[i],nums[l],nums[r]});
                    //去重
                    while(l < r && nums[l] == nums[l+1]) l++;
                    l++;
                    //去重
                    while(l < r && nums[r] == nums[r-1]) r--;
                    r--;
                }else if(sum > t){
                    while(l < r && nums[r] == nums[r-1]) r--;
                    r--;
                } 
                else{
                    while(l < r && nums[l] == nums[l+1]) l++;
                    l++;
                }
            }
        }
        return result;
    }
};

4数之和

给定一个包含 n 个整数的数组 nums 和一个目标值 target,判断 nums 中是否存在四个元素 a,b,c 和 d ,使得 a + b + c + d 的值与 target 相等?找出所有满足条件且不重复的四元组。

注意:答案中不可以包含重复的四元组。

分析

  • 2层循环 + 左右指针

算法

class Solution {

public:
    vector<vector<int>> fourSum(vector<int>& nums, int target) {
       typedef vector<vector<int>> ResultType;
       typedef typename ResultType::value_type ValueType;
       ResultType result;
       sort(nums.begin(),nums.end()); // up 
       for(auto base = 0 ; base < nums.size(); ++base){
       		// 减枝
           if(nums[base] > target/4) break;
           //第一层去重
           if(base > 0 && nums[base -1] == nums[base]) continue;
           int sum = target - nums[base];
           for(int j = base + 1; j < nums.size();++j){
           		// 减枝
               if(nums[j] > sum/3) break;
               //去重
               if(j > base + 1 && nums[j] == nums[j-1]) continue;
               int left = j+1,right = nums.size()-1,sub = sum - nums[j];
               while(left < right){
                   if(nums[left] + nums[right] == sub){
                       result.emplace_back(ValueType{nums[base],nums[j],nums[left],nums[right]});   
                       //去重 
                       while(left < right && nums[left] == nums[left+1]) ++left;
                       while(left < right && nums[right] == nums[right-1]) --right;
                       ++left;
                       --right;
                   }else if(nums[left] + nums[right] > sub){
                       while(left < right && nums[right] == nums[right-1]) --right;
                       --right;
                   }else{
                        while(left < right && nums[left] == nums[left+1]) ++left;
                       ++left;
                   };
               }
           }
       } 
       return result;
    }
};
发布了5 篇原创文章 · 获赞 0 · 访问量 47

猜你喜欢

转载自blog.csdn.net/weixin_41964962/article/details/104517677
今日推荐