zoukankan      html  css  js  c++  java
  • Leetcode(15)-三数之和

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

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

    例如, 给定数组 nums = [-1, 0, 1, 2, -1, -4],
    
    满足要求的三元组集合为:
    [
      [-1, 0, 1],
      [-1, -1, 2]
    ]

    自己的思路:如果追求思路简单,就是暴力的去求解每三个字符的和是否为0,但是有三层循环,时间复杂度太高,提交,超出时间限制。

    (1)

    • 排序。排序可以让数据变得有序,在许多算法中都有使用。
    • 定义三个指针i,left,right.
    • i用来遍历数据,从下下标为0一直到len-3。
    • 对于每一个i,令left=i+1,right=len-1,然后检查三个指针所指数据的和,
      如果为0,说明找到一个符合条件的组合,把三个数放入vector中然后再放入map中,接着把left++,right--。
      如果>0,则说明当前的right偏大,则把right--,因为是排序的,所以整体和会变小。
      如果<0,说明当前的left偏小,则把left++,因为是排序的,所以整体的和会变大。(这里变大变小不是一定的,因为可能存在重复的数据,不影响)
      vector<vector<int>> threeSum(vector<int>& nums) 
      {
          
          vector<vector<int>> result;
          int len = nums.size();
          map<vector<int>,int> m;
          if(nums.empty()||len<3) return result;
          sort(nums.begin(),nums.end());
          vector<int> res;
          int p1,p2,p3;
          int i=0;
          for(p1=0;p1<=len-3;p1++)
          {
              int left=p1+1;
              int right = len-1;
              while(left<right)
              {
                  if(nums[p1]+nums[left]+nums[right]==0)
                  {
                      res.push_back(nums[p1]);
                      res.push_back(nums[left]);
                      res.push_back(nums[right]);
                      if(!m.count(res))
                      {
                          m.insert(map<vector<int>,int>::value_type(res,i++));
                          result.push_back(res);
                      }
                      res.clear();
                      left++;
                      right--;
                  }
                  else if(nums[p1]+nums[left]+nums[right]<0)
                      left++;
                  else
                      right--;
              }
          }
          return result;
      }

      这里用map和map中的count函数是为了去除相同的组合,因为数组是排序好的,所以找到的组合也是排序好的,如果相同的话,是完全相同的,否则我们还得先排序才能比较。

    • (2)大神们还有比这个更加快速的解决方案,那就是

      vector<vector<int>> threeSum(vector<int>& nums) 
      {
              vector<vector<int>> rs;
              vector<int> res;
              if(nums.size() == 0) return rs;
              sort(nums.begin(), nums.end());//先对目标数组进行从小到大的排序
              for (int i = 0; i < nums.size() - 2; i++) 
              {
                  if (nums[i] > 0) return rs;//如果最小值都大于0,那么就不用再找了
                  if (i > 0 && nums[i] == nums[i-1]) //如果和前一个值相等,就跳过,去重
                      continue;
                  int tmpTarget = 0 - nums[i];//接下来就求nums[i]的相反数
                  
                  int beg = i + 1, end = nums.size() - 1;//也是从两边开始往中间查找
                  while (beg < end) 
                  {
                      if (nums[beg] + nums[end] == tmpTarget) 
                      {
                         res.push_back(nums[i]);
                          res.push_back(nums[beg]);
                          res.push_back(nums[end]);
                          rs.push_back(res);
                          while(beg < end - 1 && nums[end] == nums[end-1]) //同样是和前一个相同,去重
                              end--;
                          end--;
                          res.clear();
                      }
                      else if (nums[beg] + nums[end] > tmpTarget) 
                          end--;
                      else 
                          beg++;
                  }
              }
              return rs;
          }
  • 相关阅读:
    海驾学车过程全揭秘——第六篇:辛苦的学车全过程
    择偶
    海驾学车过程全揭秘——第八篇:科目二集训及考试
    海驾学车过程全揭秘——第四篇:正式练车第一段
    痛苦的相对论
    不犹豫不后悔
    海驾学车过程全揭秘——第十篇:领驾照、办牡丹卡、陪练
    海驾学车过程全揭秘——第五篇:网上约车(电话约车)
    海驾学车过程全揭秘——第一篇:总述
    海驾学车过程全揭秘——第九篇:科目三集训及考试
  • 原文地址:https://www.cnblogs.com/mini-coconut/p/9117529.html
Copyright © 2011-2022 走看看