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~n2.第二个数字(num2)选取范围num1+1~n3.第三个数字(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,通过题目!



原文地址:https://www.cnblogs.com/feichangnice/p/9025491.html

时间: 2024-08-04 08:30:47

LeeCode数组第15题三数之和的相关文章

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] ]*/ /* 思路: 首先想到的肯定是穷举,时间复杂度为O(n^3) , 但如果使用这种方法,也实在称不上算法题了,果不其然,超时. [

15、三数之和 #leetcode

给定一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?找出所有满足条件且不重复的三元组. 注意:答案中不可以包含重复的三元组. 例如, 给定数组 nums = [-1, 0, 1, 2, -1, -4], 满足要求的三元组集合为: [ [-1, 0, 1], [-1, -1, 2] ] lass Solution(object): def threeSum(self, nums): """ :type

[LeetCode] 16. 3Sum 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

LeetCode第十六题-找出数组中三数之和最接近目标值的答案

3Sum Closest 问题简介: 给定n个整数的数组nums和整数目标,在nums中找到三个整数,使得总和最接近目标,返回三个整数的总和,可以假设每个输入都只有一个解决方案 举例: 给定数组:nums=[-1, 2, 1, -4], 目标值:target = 1. 最接近目标值的答案是2 (-1 + 2 + 1 = 2). 解法一: 与上一道题类似,这次要求的是三数之和与目标值的差值最小值,可以定义一个变量来记录这个差值 思路就是想先定义一个最接近的值默认取前三个数的合,然后将数组排序后 小

LeetCode(15):三数之和

Medium! 题目描述: 给定一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?找出所有满足条件且不重复的三元组. 注意:答案中不可以包含重复的三元组. 例如, 给定数组 nums = [-1, 0, 1, 2, -1, -4], 满足要求的三元组集合为: [ [-1, 0, 1], [-1, -1, 2] ] 解题思路: 这道题让我们求三数之和,比之前那道Two Sum要复杂一些,考虑过先fix一个数,然后另外两个数使

【LeetCode每天一题】3Sum(三数之和)

Given an array nums of n integers, are there elements a, b, c in nums such that a + b + c = 0? Find all unique triplets in the array which gives the sum of zero. Note: The solution set must not contain duplicate triplets. Example: Given array nums =

lintcode 中等题: 3 Sum II 三数之和II

题目 三数之和 II 给一个包含n个整数的数组S, 找到和与给定整数target最接近的三元组,返回这三个数的和. 样例 例如S = [-1, 2, 1, -4] and target = 1.  和最接近1的三元组是 -1 + 2 + 1 = 2. 注意 只需要返回三元组之和,无需返回三元组本身 解题 和上一题差不多,程序也只是稍微修改了 public class Solution { /** * @param numbers: Give an array numbers of n integ

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 * @param {number[]} nums 3 * @return {number[][]} 4 */ 5 6var th

15.三数之和——LeetCode

1 package threesum; 2 3 import java.util.ArrayList; 4 import java.util.Arrays; 5 import java.util.List; 6 7 /** 8 * 给定一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?找出所有满足条件且不重复的三元组. 9 * 注意:答案中不可以包含重复的三元组 10 * 11 * 主要的思想:如果采用暴力法的话,时间复杂