双指针问题

最接近的三数之和

给定一个包括 n 个整数的数组 nums 和 一个目标值 target。找出 nums 中的三个整数,使得它们的和与 target 最接近。返回这三个数的和。假定每组输入只存在唯一答案。
例如,给定数组 nums = [-1,2,1,-4], 和 target = 1.
与 target 最接近的三个数的和为 2. (-1 + 2 + 1 = 2).
leetcode16
思路 采用双指针解答,先排序,指定一个下标i,另外两个数使用指针代替,前指针从i+1处开始搜索,后指针从len(nums)-1处开始搜索,计算三个数之和,判断和与target之间的距离,选取近的一组,当和大于target时,后指针减一,当和小于target时,前指针加一。
时间复杂度为 O(nlogn) + O(n^2)

class Solution:
    def threeSumClosest(self, nums: List[int], target: int) -> int:
        nums.sort()
        ans=nums[0]+nums[1]+nums[2]
        for i in range(len(nums)-2):
            if i>0 and nums[i]==nums[i-1]:continue                        #进行剪枝处理
            j=i+1
            k=len(nums)-1
            while(j<k):
                sums=nums[i]+nums[j]+nums[k]
                if abs(sums-target)<abs(ans-target):
                    ans=sums
                if sums>target:
                    k-=1
                elif sums<target:
                    j+=1
                else:
                    return target
        return ans

三数之和

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

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

例如, 给定数组 nums = [-1, 0, 1, 2, -1, -4],

满足要求的三元组集合为:
[
[-1, 0, 1],
[-1, -1, 2]
]

方法一 方法一和上面的题类似,上题是寻找距离目标最近的三数之和,这道题是寻找等于0的三个数,大概思路和上题相同,只是在目标上稍加修改,仍然采用双指针,先排序,指定一个数的位置,移动前后双指针,判断三数之和与0是否相等,当大于0时后指针-1,当小于0时前指针+1,注意这里需要不重复的三元组,因此需要跳过相同的元素。

class Solution:
    def threeSum(self, nums: List[int]) -> List[List[int]]:
        nums.sort()
        res=[]
        for k in range(len(nums)-2):
            if nums[k]>0:break
            if k>0 and nums[k]==nums[k-1]:continue
            i,j=k+1,len(nums)-1
            while i<j:
                s=nums[k]+nums[i]+nums[j]
                if s<0:
                    i+=1
                    while i<j and nums[i]==nums[i-1]:i+=1
                elif s>0:
                    j-=1
                    while i<j and nums[j]==nums[j+1]:j-=1
                else:
                    res.append([nums[k],nums[i],nums[j]])
                    i+=1
                    j-=1
                    while i<j and nums[i]==nums[i-1]:i+=1
                    while i<j and nums[j]==nums[j+1]:j-=1
        return res

方法二 细看可发现方法一的时间复杂较高,因此这里采用字典减少时间复杂度,空间换时间,创建一个字典,将数组中的值和其出现次数放入字典中,若和为0,那么肯定正负相加为0或全为0,因此可将数分为正负两种,之后判断第三个数是否在字典中,数组中出现不重复,重复等问题都可考虑字典是否能解决。

nums.sort()
hash_map={}
res=[]
for num in nums:
    hash_map[num]=hash_map.get(num,0)+1
neg=[x for x in hash_map if x<0]
pos=[x for x in hash_map if x>0]
if 0 in hash_map and hash_map[0]>2:
    res.append([0,0,0])
for x in neg:
    for y in pos:
        another=-x-y
        if another in hash_map:
            if another in (x,y) and hash_map[another]>1:
                res.append([x,another,y])
            if another>x and another<y:
                res.append([x,another,y])
return res
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值