LeetCode(3 Sum, 4sum, ksum)

题目要求:

Given an array S of n integers, are there elements abc in S such that a + b + c = 0? Find all unique triplets in the array which gives the sum of zero.

Note:

  • Elements in a triplet (a,b,c) must be in non-descending order. (ie, a ≤ b ≤ c)
  • The solution set must not contain duplicate triplets.

    For example, given array S = {-1 0 1 2 -1 -4},

    A solution set is:
    (-1, 0, 1)
    (-1, -1, 2)
思路:这个问题可以退化成先找一个数a, 然后在剩下的集合中找两个数使它们的和为 target - a; 所以先将数组排序,然后顺次遍历, 使当前数位选中的数,再在剩余的集合中找到符合要求的两个数。

代码:

 vector<vector<int> > threeSum(vector<int> &num)
  {
    sort(num.begin(), num.end());
//    return DFS(num, 0, 3, 0);
    ans.clear();
    if(num.size() < 3)
      return ans;
    int count = num.size() - 2;
    vector<int> triple(3, 0);
    int current = num[0];
    triple[0] = num[0];
    //每次挑出一个数
    for(size_t i = 0; i < count; ++i)
    {
      if(i && num[i] == current)
        continue;
      triple[0] = num[i];
      int j = i + 1;
      int k = num.size() - 1;
      while(j < k)
      {
        int sum = triple[0] + num[j] + num[k];
        if(sum  == 0)
        {
          triple[1] = num[j];
          triple[2] = num[k];
          //因为都是按顺序找的所以出现重复也肯定是相邻的
          if(ans.size() == 0 || triple != ans[ans.size() - 1])
            ans.push_back(triple);
          ++j;
          --k;
        }
        else if(sum  > 0)
          --k;
        else 
          ++j;
      }
      current = num[i];
    }
    return ans;
  }
  

3-sum closest

题目要求:

Given an array S of n integers, find three integers in S such that the sum is closest to a given number, target. Return the sum of the three integers. You may assume that each input would have exactly one solution.

    For example, given array S = {-1 2 1 -4}, and target = 1.

    The sum that is closest to the target is 2. (-1 + 2 + 1 = 2).
思路与3 sum差不多,就是在找的过程中记录更新最小值。最后返回:

代码:

 int threeSumClosest(vector<int> &num, int target) 
  {
    if(num.size() < 3)
      return abs(target);
    sort(num.begin(), num.end());
    int min_dist = numeric_limits<int>::max();
    int res;
    for(size_t i = 0; i < num.size(); ++i)
    {
      int j = i + 1, k = num.size() - 1;
      int sum = 0;
      while(j < k)
      {
        sum = num[i] + num[j] + num[k];
        if(sum == target)
          return sum;
        else if(sum > target)
          --k;
        else 
          ++j;
        if(min_dist > abs(sum - target))
        {
          min_dist = abs(sum - target);
          res = sum;
        }
      }
    }
    return res;
  }

4-sum

Given an array S of n integers, are there elements abc, and d in S such that a + b + c + d = target? Find all unique quadruplets in the array which gives the sum of target.

Note:

  • Elements in a quadruplet (a,b,c,d) must be in non-descending order. (ie, a ≤ b ≤ c ≤ d)
  • The solution set must not contain duplicate quadruplets.

    For example, given array S = {1 0 -1 0 -2 2}, and target = 0.

    A solution set is:
    (-1,  0, 0, 1)
    (-2, -1, 1, 2)
    (-2,  0, 0, 2)
思路: 与3-sum的做法差不多, 只是这次要先选两个数,然后再在剩下的数组中找到符合要求的另外两个数, 其实最后一步步退化成2-sum

代码:

vector<vector<int> > fourSum(vector<int> &num, int target) {
    vector<vector<int> > ret;
    set<vector<int> > unique_res;
    if(num.size() < 4)
      return ret;
    sort(num.begin(), num.end());
    vector<int> tmp_four(4, 0);
    for(size_t i = 0; i < num.size(); ++i)
    {
      for(size_t j = i + 1; j < num.size(); ++j)
      {
        tmp_four[0] = num[i], tmp_four[1] = num[j];
        int begin = j + 1, end = num.size() - 1;
        while(begin < end)
        {
          int sum = tmp_four[0] + tmp_four[1] + num[begin] + num[end];
          if(sum == target)
          {
            tmp_four[2] = num[begin];
            tmp_four[3] = num[end];
            unique_res.insert(tmp_four);
            --end;
            ++begin;
          }
          else if(sum > target)
            --end;
          else 
            ++begin;
        }
      }
    }
    for(set<vector<int> >::iterator iter = unique_res.begin(); iter != unique_res.end();
        ++iter)
      ret.push_back(*iter);
    return ret;
  }
  

K-sum

思路与3-sum和4-sum,一步步退化成找2-sum

代码:

 vector<vector<int> > DFS(vector<int>& num, int begin, int count, int sum)
  {
   // const int len = num.size();
    set<int> visited;
    vector<vector<int> > ret;
    vector<int> triple;
    if(count == 2)
    {
      int i = begin, j = num.size() - 1;
      while(i < j)
      {
        if((num[i] + num[j]) == sum)
        {
          triple.clear();
          triple.push_back(num[i]);
          triple.push_back(num[j]);
          ret.push_back(triple);
          ++i;
          --j;
        }
        else if((num[i] + num[j]) > sum)
          --j;
        else
          ++i;
      }
    }
    else 
    {
      for(size_t i = begin; i < num.size(); ++i)
      {
        if(visited.count(num[i]) == 0)
        {
          visited.insert(num[i]);
          vector<vector<int> > subset = DFS(num, i + 1, count - 1, sum - num[i]);
          if(!subset.empty())
          {
            for(size_t j = 0; j < subset.size(); ++j)
              subset[j].insert(subset[j].begin(), num[i]);
            ret.insert(ret.end(), subset.begin(), subset.end());
          }
        }
      }
    }
    return ret;
  }
  



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值