zoukankan      html  css  js  c++  java
  • LeeCode数组第15题三数之和

    题目:三数之和

    内容

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

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

    例如, 给定数组 nums = [-1, 0, 1, 2, -1, -4],
    
    满足要求的三元组集合为:
    [
      [-1, 0, 1],
      [-1, -1, 2]
    ]
    思路
    题目实现可分为两个步骤,分别是(1)寻找三个满足条件的元素(2)去重复
    对于第一个小问题,首先考虑三个for循环,直接寻找
    1.第一个数字(num1)选取范围1~n
    2.第二个数字(num2)选取范围num1+1~n
    3.第三个数字(num3)选取范围num2+1~n
    代码如下:
     1 //寻找三数之和为0的数 C++
     2             vector<int> vec(3);
     3             unsigned int num1 = 0, num2 = 0, num3 = 0;
     4             for (num1; num1 < nums.size() - 2; num1++){
     5                 for (num2 = num1 + 1; num2 < nums.size() - 1; num2++){
     6                     for (num3 = num2 + 1; num3 < nums.size(); num3++){
     7                         if (nums[num1] + nums[num2] + nums[num3] == 0){
     8                             vec[0] = nums[num1];
     9                             vec[1] = nums[num2];
    10                             vec[2] = nums[num3];
    11                             vecs.push_back(vec);
    12                         }
    13                     }
    14                 }
    15             }

    第二个小问题去重复

    C++ 的STL提供有去重算法unique,直接去重即可

    1.在寻找满足条件的三个数字之前要先排序,防止相同的vec因为内部元素顺序不同去不了重复,如[1,2,3]和[2,1,3]会判定为不重复

    2.对于vecs结果进行去重,去重之前一定要再次排序,因为unique函数只是比较相邻的两个元素是否重复,如果重复就将重复的放到尾部,如果不限排序,对于vecs[[1,2,3],[0,0,0],[1,2,3]],因为相邻的元素都不想等([1,2,3]≠[0,0,0]),系统会去重失败

    去重代码如下:

    1 //先排序,方便去重
    2             sort(nums.begin(), nums.end());
    3 //寻找三个满足条件的数字代码省略。。。。
    4 //去重
    5             sort(vecs.begin(), vecs.end());
    6             vecs.erase(unique(vecs.begin(), vecs.end()), vecs.end());
    7 
    8             return vecs;

    此外,还要考虑异常的情况,当传入的数组长度小于3时,无法给出满足条件的解,应返回空的容器

    完整代码如下:

     1 vector<vector<int>> threeSum(vector<int>& nums) {
     2             vector<vector<int>> vecs;
     3             //异常判断
     4             if (nums.size() < 3)
     5                 return vecs;
     6 
     7             //先排序,方便去重
     8             sort(nums.begin(), nums.end());
     9 
    10             //寻找三数之和为0的数
    11             vector<int> vec(3);
    12             unsigned int num1 = 0, num2 = 0, num3 = 0;
    13             for (num1; num1 < nums.size() - 2; num1++){
    14                 for (num2 = num1 + 1; num2 < nums.size() - 1; num2++){
    15                     for (num3 = num2 + 1; num3 < nums.size(); num3++){
    16                         if (nums[num1] + nums[num2] + nums[num3] == 0){
    17                             vec[0] = nums[num1];
    18                             vec[1] = nums[num2];
    19                             vec[2] = nums[num3];
    20                             vecs.push_back(vec);
    21                         }
    22                     }
    23                 }
    24             }
    25 
    26             //去重
    27             sort(vecs.begin(), vecs.end());
    28             vecs.erase(unique(vecs.begin(), vecs.end()), vecs.end());
    29 
    30             return vecs;
    31     }

    对于较短的输入,能给出合适的结果,然后对于巨长的数组,系统提示运算时间过长,因此需要优化代码。

    根据题目所给的条件,可以看出三个数字之和是定值,因此,当我们选取第一个数字num1后,问题变为寻找和为0-num1的两个数字。

    可以观察到,因为数组是有序的,我们可以设置两个指针从两边同时选取

     1 int targetSum = 0 - nums[num1];
     2             while (pLeft < pRight ){
     3                 int sum = nums[pLeft] + nums[pRight];
     4                 if (sum > targetSum || nums[pRight] == nums[pRight-1]){
     5                     pRight--;
     6                 }
     7                 else if (sum < targetSum || nums[pLeft] == nums[pLeft - 1]){
     8                     pLeft++;
     9                 }
    10                 else{
    11                     vec[0] = nums[num1];
    12                     vec[1] = nums[pLeft];
    13                     vec[2] = nums[pRight];
    14                     vecs.push_back(vec);
    15                     pLeft++;
    16                     pRight--;
    17                 }
    18             }

    也因为数组是排序的,为了如果我们选取的第一个数子大于0,则后两个必然大于0,可以跳出循环

    对于重复的数字,我们可以选择跳过

    完整代码如下:

     1 vector<vector<int>> threeSum(vector<int>& nums) {
     2         vector<vector<int>> vecs;
     3         //异常判断
     4         if (nums.size() < 3)
     5             return vecs;
     6 
     7         //先排序,方便去重
     8         sort(nums.begin(), nums.end());
     9         
    10         //寻找三数之和为0的数
    11         vector<int> vec(3);
    12         unsigned int num1 = 0, num2 = 0, num3 = 0;
    13         for (num1; num1 < nums.size() - 2; num1++){
    14             if (nums[num1] * 3 > 0)//数组是从小到大排序
    15                 break;
    16             if (num1 != 0 && nums[num1] == nums[num1 - 1])
    17                 continue;
    18 
    19             int pLeft, pRight;
    20             pLeft = num1+1;
    21             pRight = nums.size() - 1;
    22             
    23             int targetSum = 0 - nums[num1];
    24             while (pLeft < pRight ){
    25                 int sum = nums[pLeft] + nums[pRight];
    26                 if (sum > targetSum || nums[pRight] == nums[pRight-1]){
    27                     pRight--;
    28                 }
    29                 else if (sum < targetSum || nums[pLeft] == nums[pLeft - 1]){
    30                     pLeft++;
    31                 }
    32                 else{
    33                     vec[0] = nums[num1];
    34                     vec[1] = nums[pLeft];
    35                     vec[2] = nums[pRight];
    36                     vecs.push_back(vec);
    37                     pLeft++;
    38                     pRight--;
    39                 }
    40             }
    41         }
    42 
    43         //去重
    44         sort(vecs.begin(), vecs.end());
    45         vecs.erase(unique(vecs.begin(), vecs.end()), vecs.end());
    46 
    47 
    48         return vecs;
    49     }

    对于复杂测试案例的运行时间是60ms,通过题目!



  • 相关阅读:
    Spring Cloud Hystrix Dashboard的使用 5.1.3
    Spring Cloud Hystrix 服务容错保护 5.1
    Spring Cloud Ribbon 客户端负载均衡 4.3
    Spring Cloud 如何实现服务间的调用 4.2.3
    hadoop3.1集成yarn ha
    hadoop3.1 hdfs的api使用
    hadoop3.1 ha高可用部署
    hadoop3.1 分布式集群部署
    hadoop3.1伪分布式部署
    KVM(八)使用 libvirt 迁移 QEMU/KVM 虚机和 Nova 虚机
  • 原文地址:https://www.cnblogs.com/feichangnice/p/9025491.html
Copyright © 2011-2022 走看看