15. 3Sum[M]三数之和
题目
Given an array nums of n integers, are three 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 = [-1, 0, 1, 2, -1, -4],
A solution set is:
[[-1, 0, 1],[-1, -1, 2]]
思路
双指针法变种——三指针法(这里的指针指的是数组下标)
- 要保证三个数a+b+c=0;
- 至少要保证有一个数是0或者负数,
- 但是由于数组是乱序排列的,很难直接判断是否有0或负数,于是想到将数组排序
- 将等式改写为b+c = -a,如何找到
- 首先保证a是非正数(0或负数)
- 如何找到b和c使之与-a相等?
- 定义中间指针p2、尾指针p3,移动的方向为往中间移动

图1:指针移动示意图
- 不能有重复结果
- 在最外层循环时,跳过已经判断过的数字
- p2、p3往中间移动时,跳过重复元素
于是
Step1:将数组排序
Step2:以第一个数p1作为最外层循环,其中如果第一个数如果为正,说明和不可能为0
Step3:定义中间指针p2,尾指针p3,
- 如果num[p2] + num[p3] > -nums[p1],则说明和太小了,应该往数值大的方向的移动,p2++
- 如果num[p2] + num[p3] < -nums[p1],则说明和太大了,应该往数值小的方向的移动,p3--
- 如果num[p2] + num[p3] = -nums[p1],将结果保存,同时将p2、p3往中间移动,为了保证结果的唯一性,需要跳过重复元素
Tips
列表方法(python)
方法是作用于Python中特定类型对象的函数。列表类型拥有9个只作用于列表的方法,分为两类
- 改变列表的方法
- 不改变列表的方法
以列表aList = [ 2, 1, 3, 'a', 4 ]
为例(假设每个方法下的例子都是独立的,不会互相影响):
1. 不修改列表的方法
index(x)
返回列表中与x值相等的第一个元素的索引。如果在列表中没有找到这样的元素,Python将报错。
aList.index(3) #输出2
count(x)
返回列表中x出现的次数。如果列表中不包含x,返回0。
aList.count(1) #输出1
2. 修改列表的方法
append(x)
在列表的末尾添加元素。列表长度增加1,如果append的参数时列表,则该列表(包括方括号)将作为单个元素加入列表中。
aList.append(5) #输出是[2, 1, 3, 'a', 4, 5]
aList.append([5, 6, 7]) #输出是[2, 1, 3, 'a', 4, [5, 6, 7] ]
pop()
删除列表末尾的元素,并返回此元素。列表变短,少了一个元素。如果指定索引值,则array.pop(index)将删除该索引位置的元素并返回该项。
aList.pop() #输出4
extend(A)
需要一个集合作为参数。将该集合中的每个元素添加到列表的末尾,从而扩展列表。
anotherList=[5, 6]
aList.extend(anotherList) #输出是[2, 1, 3, 'a', 4, 5, 6]
insert(index, x)
在指定位置插入元素。第一个参数是元素插入前的索引。如果x是一个列表,则该列表(包括方括号)将作为单个元素加入列表中。
aList.insert(2, 'b') #输出是[2, 1, 'b', 3, 'a', 4]
remove(x)
删除列表中第一个值为x的元素。如果没有该元素,将出错。
aList.remove(2) #输出是[1, 3, 'a', 4]
sort()
将列表中的元素进行排序。与sorted函数比较,sorted返回排好序的列表,但是不改变原列表。如果要对列表的列表进行排序,则只考虑每个列表的首元素。
aList.sort() #输出是[1, 2, 3, 4, 'a']
reverse()
将列表中的元素反向排列。
aList.reverse() #输出是['a', 4, 3, 2, 1]
C++
vector<vector<int>> threeSum(vector<int>& nums) {
vector<vector<int> > resVec;
sort(nums.begin(),nums.end()); //将nums从小到大排序
for(int p1=0;p1<nums.size();p1++){
if(nums[p1] >0) //如果第一个数为正数,说明肯定不存在三个数
return resVec;
if(p1>0 && nums[p1] == nums[p1-1]) //由于结果需要唯一性,故去除nums中的重复元素
continue;
int p2 = p1+1;//中间指针
int p3 = nums.size()-1;//尾指针
while(p2<p3){
int a = nums[p1];//非正
int b = nums[p2];
int c = nums[p3];
if(b+c== -a){
vector<int> tempVec(3);
tempVec[0] = a;
tempVec[1] = b;
tempVec[2] = c;
resVec.push_back(tempVec);
while (p2 < p3 && nums[p2] == nums[p2 + 1]) //去除重复元素
p2++;
while (p2 < p3 && nums[p3 - 1] == nums[p3]) //去除重复元素
p3--;
p2++;
p3--;
}
else if(b+c < -a){ //如果b+c之和小于-a,说明和太小了,应该往数值大的方向的移动
p2++;
}
else{ //反之,如果b+c之和大于-a,说明和太大了,应该往数值小的方向的移动
p3--;
}
}
}
return resVec;
}
Python
class Solution(object):
def threeSum(self, nums):
"""
:type nums: List[int]
:rtype: List[List[int]]
"""
nums.sort()
result = [ ]
for p1 in range(len(nums)):
if nums[p1] > 0:
return result
if p1 > 0 and nums[p1] == nums[p1-1]:
continue
p2 = p1 + 1
p3 = len(nums) - 1
while p2 < p3:
a = nums[p1]
b = nums[p2]
c = nums[p3]
if(b + c == -a):
result.append([a, b, c])
while p2 < p3 and nums[p2] == nums[p2+1]:
p2 += 1
while p2 < p3 and nums[p3-1] == nums[p3]:
p3 -= 1
p2 += 1
p3 -= 1
elif(b + c < -a):
p2 += 1
else:
p3 -= 1
return result
参考
[1] Python入门经典
15. 3Sum[M]三数之和的更多相关文章
- LeetCode 15. 3Sum(三数之和)
Given an array S of n integers, are there elements a, b, c in S such that a + b + c = 0? Find all un ...
- [LeetCode] 259. 3Sum Smaller 三数之和较小值
Given an array of n integers nums and a target, find the number of index triplets i, j, k with 0 < ...
- [LeetCode] 3Sum Smaller 三数之和较小值
Given an array of n integers nums and a target, find the number of index triplets i, j, k with 0 < ...
- LeetCode(15):三数之和
Medium! 题目描述: 给定一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?找出所有满足条件且不重复的三元组. 注意:答 ...
- leetcode第15题:三数之和
给定一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?找出所有满足条件且不重复的三元组. 注意:答案中不可以包含重复的三元组. ...
- 15 3Sum(寻找三个数之和为指定数的集合Medium)
题目意思:给一个乱序数组,在里面寻找三个数之和为0的所有情况,这些情况不能重复,增序排列 思路:前面2sum,我用的是map,自然那道题map比双指针效率高,这道题需要先排序,再给三个指针,i.j.k ...
- LeetCode#15 | Three Sum 三数之和
一.题目 给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有满足条件且不重复的三元组. 注意:答案中不可以包含 ...
- LeetCode第[15]题(Java):3Sum (三数之和为目标值)——Medium
题目难度:Medium 题目: Given an array S of n integers, are there elements a, b, c in S such that a + b + c ...
- 3sum 求三数之和等于0,不允许重复
https://leetcode.com/problems/3sum/ 套路比较常见了,最重要的是去重.还是没法一次通过. class Solution { public: vector<vec ...
随机推荐
- BZOJ4517: [Sdoi2016]排列计数(组合数+错位排列)
Time Limit: 60 Sec Memory Limit: 128 MBSubmit: 1626 Solved: 994[Submit][Status][Discuss] Descripti ...
- the selection cannot be run on any server
导入war包后运行jsp 显示: the selection cannot be run on any server 问题原因: Dynamic Web Module 的版本与server不匹配.Dy ...
- arttemplate.js简洁写法案例
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8&quo ...
- C#多线程(Thread)开发基础
除非另有说明,否则所有的例子都假定以下命名空间被引用: using System; using System.Threading; 1 基本概念 在描述多线程之前,首先需要明确一些基本概念. ...
- VS2012 +PTVS配置
使用PTVS可以在Vs中使用Python,可以作为一个小TIps,总体来说还是不太合算,有多少价值呢!? 可以使用Python,可以直接构建Python工程.... 我下载的是 2.0beta版本: ...
- Java学习笔记2——数据类型和转换
前提知识: 1字节=8bit:1bit以一个二极管表示,代表2个状态(0或者1):2bit代表22即4种状态(00,01,10,11),8bit即是28即256种状态,16bit即是65536种状态. ...
- MySQL-字符类型与约束条件
创建表完整的语法: create table 表名(字段名1 类型[(宽度) 约束条件],字段名2 类型[(宽度) 约束条件],字段名3 类型[(宽度) 约束条件]); 注意事项: 1. 在同一张表中 ...
- 洛谷P1914 小书童——密码
题目背景 某蒟蒻迷上了"小书童",有一天登陆时忘记密码了(他没绑定邮箱or手机),于是便把问题抛给了神犇你. 题目描述 蒟蒻虽然忘记密码,但他还记得密码是由一串字母组成.且密码是由 ...
- [网络流24题] 太空飞行计划问题 (最大流->最大权闭合图)
洛谷传送门 LOJ传送门 做这道题之前建议先看这篇论文,虽然论文里很多地方用了很多术语,但hbt神犇讲得很明白 这篇题解更加偏向于感性理解 把问题放到二分图上,左侧一列点是实验,权值为$p[i]$,右 ...
- JAVA 上传图片功能
前后端实现上传图片功能(JAVA代码) 1.前端大概 请求头必须为AJAX请求头: 'X-Requested-With': 'XMLHttpRequest' 一般是指网页中存在的Content-Typ ...