当前位置:网站首页>两数,三数之和
两数,三数之和
2022-07-25 20:46:00 【我家大宝最可爱】
1. 两数之和
给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。
示例 1:
输入:nums = [2,3,5,7,11,13], target = 12
输出:[2,3]
解释:因为 nums[2] + nums[3] == 12 ,返回 [2, 3] 。
1. 两个循环
最直接的解法就是数组的数两两组合,然后求出和即可,这个直接使用两个循环即可,因为是两两组合,并且不需要重复,所以j直接从i后面开始选取即可
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
n = len(nums)
for i in range(n):
for j in range(i+1,n):
if nums[i] + nums[j] == target:
return i,j
2. 排序+双指针
如果不考虑位置,直接返回两个数据,我们还有一种双指针的方法。双指针的思想也非常的简单,我们首先对数组进行升序排序,然后两个指针分别指向头和尾
if nums[L]+nums[R]>tartet : R-=1if nums[L]+nums[R]<tartet : L+=1
| 2 | 3 | 5 | 7 | 11 | 13 |
|---|---|---|---|---|---|
| L | R |
2+13>12,此时两个数的和大于目标值,我们移动右指针,这样可以让两个数的和小一点
| 2 | 3 | 5 | 7 | 11 | 13 |
|---|---|---|---|---|---|
| L | R |
2+11>12,此时两个数的和大于目标值,我们移动右指针,这样可以让两个数的和小一点
| 2 | 3 | 5 | 7 | 11 | 13 |
|---|---|---|---|---|---|
| L | R |
2+7<12,此时两个数的和小于目标值,我们移动左指针,这样可以让两个数的和大一点
| 2 | 3 | 5 | 7 | 11 | 13 |
|---|---|---|---|---|---|
| L | R |
3+7<12,此时两个数的和小于目标值,我们移动左指针,这样可以让两个数的和大一点
| 2 | 3 | 5 | 7 | 11 | 13 |
|---|---|---|---|---|---|
| L | R |
5+7=12,找到了一组数据。
可以看到,双指针的第一步就是对数组进行排序,这会直接打乱原来数组的顺序,因此即使得到了满足targe的两个数据,也需要通过index函数映射回去
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
arr = zip(nums,range(len(nums)))
arr = sorted(arr, key=lambda x:x[0])
l,r=0,len(nums)-1
while l < r:
print(l,r)
if arr[l][0]+arr[r][0]>target:r-=1
elif arr[l][0]+arr[r][0]<target:l+=1
else: return arr[l][1],arr[r][1]
3. hash
然后我看了另一种解法,也是非常的巧妙,使用hash表来存储数据。对于数组中的某个数nums[i],我们需要找到一个数满足target-nums[i],即在原始的数组中查找是否存在一个数nums[j]=target-nums[i],这就转变成了一个查找问题。
nums[i] | 2 | 7 | 11 | 5 |
|---|---|---|---|---|
nums[j]=target-nums[i] | 9-2=7 | 9-7=2 | 9-11=-2 | 9-5=4 |
三数之和
给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有和为 0 且不重复的三元组。
注意:答案中不可以包含重复的三元组。
示例 1:
输入:nums = [-1,0,1,2,-1,-4]
输出:[[-1,-1,2],[-1,0,1]]
1. 三层循环(暴力算法无所畏惧)
最直接的想法就是三层for循环来求解三个数组的组合。不过调试的过程中发现数组中会出现相同的元素,这就回导致出现重复的结果,例如示例1,由于重复出现了-1,因此在循环的过程中也出现了重复,即第一个-1和第二个-1都可以与0,1组合后满足结果,因此出现了两次。
[[-1,0,1],[-1,2,-1],[0,1,-1]]
class Solution:
def threeSum(self, nums: List[int]) -> List[List[int]]:
res = []
n = len(nums)
for i in range(n):
for j in range(i+1,n):
for k in range(j+1,n):
if nums[i] + nums[j] + nums[k] == 0:
res.append([nums[i],nums[j],nums[k]])
return res
我们可以通过对数组排序来处理重复问题,可以看到有两个-1,我分别用红色和绿色标记出来。
- 第一个-1会与0,1,2进行组合,第二个-1也会与0,1,2进行组合,这就会导致重复的结果,因此我们只需要选择一个-1就可以了
- 应该选择哪一个-1呢?很明显应该选择第一个-1,因为第一个-1还可以与第二个-1进行组合,第一个-1的组合数已经包含了第二个-1的组合数

class Solution:
def threeSum(self, nums: List[int]) -> List[List[int]]:
res = []
nums.sort()
n = len(nums)
for i in range(n):
if i > 0 and nums[i] == nums[i-1]:continue # 保留第一个
for j in range(i+1,n):
for k in range(j+1,n):
if nums[i] + nums[j] + nums[k] == 0:
res.append([nums[i],nums[j],nums[k]])
return res
这样依然会有重复的问题,举个例子nums=[-5,0,2,2,3,3],会出现两次2,3的结果,因此内部的循环依然需要做判断,但是通过循环很难去重了。可以使用双指针来去重
2.排序+双指针
数组已经排好了顺序,我们之前求解两数之和的时候,也使用了双指针的方法。但是现在需要考虑去重的问题。确定第一个元素之后,我们使用两个指针分别指向头和尾
if nums[F] + nums[L]+nums[R]>0 : R-=1if nums[F] + nums[L]+nums[R]<0 : L+=1
| -6 | -5 | 1 | 2 | 2 | 3 | 3 | 4 |
|---|---|---|---|---|---|---|---|
| First | L | R | |||||
| First | L | R | |||||
| First | L | R |
现在我们已经求出了一组解了,但是题目要求的是让我们把所有的可行解都求解出来,所以需要继续移动双指针。但是这个case可以发现如果我们移动做指针得到的依然是重复解,因此需要去重,即
while L < R and nums[L]==nums[L+1]:L+=1while L < R and nums[R]==nums[R-1]:R-=1
核心点:通过循环一直到找到下一个不同的数字即可
class Solution:
def threeSum(self, nums: List[int]) -> List[List[int]]:
res = []
nums.sort()
n = len(nums)
for i in range(n):
if i > 0 and nums[i] == nums[i-1]:continue
l,r=i+1,n-1
while l < r:
if nums[l]+nums[r]>-nums[i]:
r -= 1
elif nums[l]+nums[r]<-nums[i]:
l += 1
else:
res.append([nums[l],nums[r],nums[i]])
while l < r and nums[l] == nums[l+1]:l += 1
while l < r and nums[r] == nums[r-1]:r -= 1
l += 1
r -= 1
return res
循环变搜索
明明是两层循环为什么改成双指针之后就可以只需要循环一次了呢?这是因为排完序之后,双指针可以过滤很多不需要循环的操作。
举个具体的case,例如求两数之和,其中nums = [2,3,5,7,11,13], target = 12,
for i in range(n):
for j in range(i+1,n):
print(nums[i],nums[j])
if nums[i]+nums[j] == target:
res.append(nums[i],nums[j])
如果我们先确定一个数2,然后跟后面的2,3,5,7,11,13进行组合,当我们组合到11的时候2+11>13,那么我们还需要去跟更大的13去组合吗,显然是不需要的,所以我们可以直接加一个判断,跳过后面的数字
for i in range(n):
for j in range(i+1,n):
print(nums[i],nums[j])
if nums[i]+nums[j] == target:
res.append(nums[i],nums[j])
elif nums[i]+nums[j] > target:
break
现在就回发现一个有趣的点了,2和11组合大于12,因此2不需要再跟13组合,那么第一层循环是3,还需要跟11和13组合吗,肯定也不需要了,也就是说,我们第二层循环的结尾不一定始终是n,而是可以不断往前推的
r = n
for i in range(n):
for j in range(i+1,r):
print(nums[i],nums[j])
if nums[i]+nums[j] == target:
res.append(nums[i],nums[j])
elif nums[i]+nums[j] > target:
r = j
break
边栏推荐
- Leetcode-6129: number of all 0 subarrays
- Remote - basic principle introduction
- 【NOI模拟赛】字符串匹配(后缀自动机SAM,莫队,分块)
- 牛客-TOP101-BM37
- Remote—基本原理介绍
- 结构体,枚举类型与联合体
- Golang language quickly get started to comprehensive practical notes (go language, beego framework, high concurrency chat room, crawler)
- [tensorrt] dynamic batch reasoning
- 476-82(322、64、2、46、62、114)
- 数据库清空表数据并让主键从1开始
猜你喜欢

Compilation and operation of program
![[advanced mathematics] [1] function, limit, continuity](/img/c5/f9fd3814a61d0fba24b37253c7e51c.png)
[advanced mathematics] [1] function, limit, continuity

Key network protocols in tcp/ip four layer model

Online random coin tossing positive and negative statistical tool
![[leetcode] 28. Implement strstr ()](/img/87/0af2da458e53d31012d6535cc132bb.png)
[leetcode] 28. Implement strstr ()

Card link

Working principle of radar water level gauge and precautions for installation and maintenance
![[today in history] July 17: Softbank acquired arm; The first email interruption; Wikimedia International Conference](/img/0f/8ce2d5487b16d38a152cfd3ab454bb.png)
[today in history] July 17: Softbank acquired arm; The first email interruption; Wikimedia International Conference

Online XML to JSON tool
![[today in history] July 8: PostgreSQL release; SUSE acquires the largest service provider of k8s; Activision Blizzard merger](/img/14/f2b68dbe4e6a9b8d89ed9ff38f5e11.png)
[today in history] July 8: PostgreSQL release; SUSE acquires the largest service provider of k8s; Activision Blizzard merger
随机推荐
Vulnhub | dc: 5 | [actual combat]
MySQL master-slave replication data synchronization, summary of common problems
Question and answer 47: geeks have an appointment - the current monitoring system construction of CSC
leetcode-6127:优质数对的数目
PayPal PHP product trial period "recommended collection"
[today in history] July 17: Softbank acquired arm; The first email interruption; Wikimedia International Conference
Using the OAP aspect causes the controller to be called repeatedly
Unity VS—— VS中默认调试为启动而不是附加到Unity调试
Too many passwords, don't know how to record? Why don't you write a password box applet yourself
[noi simulation] string matching (suffix automata Sam, Mo team, block)
Working principle of radar water level gauge and precautions for installation and maintenance
Leetcode-919: complete binary tree inserter
火山引擎项亮:机器学习与智能推荐平台多云部署解决方案正式发布
MySQL date [plus sign / +] condition filtering problem
leetcode-6129:全 0 子数组的数目
process.env
Basic knowledge of Marine Geology
Fanoutexchange switch code tutorial
Mobile web layout method
leetcode-79:单词搜索