算法34--3Sum,3Sum Closest,4Sum

Given an array nums of n integers, are there elements abc 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]
]

给定一个数组,选出三元组使其和为0  三元组不能重复。

将数组排序,固定第一个指针k来进行遍历,然后利用双指针i,j分别从数组k+1--len-1向中点寻找,

当sum=nums[k]+nums[i]+nums[j]==0  直接输出

当sum<0,说明过小,此时移动i指针即可,i++,否则移动j即可,j--

def threeSum(nums=[-2,0,0,2,2]):
        nums.sort()
        #print(nums)
        rr = []
        for k in range(len(nums)-1):
            i = k+1                        
            j = len(nums)-1        
            while i<j:
                #print(k, i, j)                
                sum = nums[k] + nums[i] + nums[j]
                if sum==0:
                    rr.append([nums[k], nums[i], nums[j]])                                           
                    i += 1
                    j -= 1
                elif sum<0:
                    i += 1
                else:
                    j -= 1
        return rr

代码如上所示,输出结果并没有去除重复结果,现在考虑一下重复值的产生情况:

给定数组以及三个指针k,i,j     0---k---i----j---len-1

当nums[k-1]==nums[k]相同时,可以直接k++,进行下一次循环,否则可能会产生重复  例如  -1   -1  0  1  1当k=0与k=1时会产生重复;

当k遍历依次递加没有重复,考虑i位置的重复,当某一元组(k,i,j)符合条件时,此时如果nums[i+1]==nums[j],此时如果执行i++,j--,可能会产生重复,处理方式是当找到符合条件的三元组时,此时应该移动i,j的指针直到nums[i·]不等于nums[i],以及nums[j`]不等于nums[j]

def threeSum(nums=[-2,0,0,2,2]):
        nums.sort()
        #print(nums)
        rr = []
        for k in range(len(nums)-1):
            if k>=1 and nums[k-1]==nums[k]:
                continue
            i = k+1                        
            j = len(nums)-1        
            while i<j:
                #print(k, i, j)                
                sum = nums[k] + nums[i] + nums[j]
                if sum==0:
                    rr.append([nums[k], nums[i], nums[j]])                        
                    while i<j and nums[i+1]==nums[i]:                        
                        i += 1
                    while i<j and nums[j-1]==nums[i]:
                        j -= 1
                    i += 1
                    j -= 1
                elif sum<0:
                    i += 1
                else:
                    j -= 1
        return rr

Given an array nums of n integers and an integer target, find three integers in nums such that the sum is closest to target. Return the sum of the three integers. You may assume that each input would have exactly one solution.

Example:

Given array nums = [-1, 2, 1, -4], and target = 1.

The sum that is closest to the target is 2. (-1 + 2 + 1 = 2).

给定数组,找到一个三元组,使其和最接近target.

将数组排序,维持一个全局最小差值,利用数组有序以及三指针来调整位置,寻找可能的最小差值

def threeSumClosest(nums=[-4,-1,1,2], target=1):
        """
        :type nums: List[int]
        :type target: int
        :rtype: int
        """
        nums.sort()
        minv = nums[0]+nums[1]+nums[-1]
        mind = abs(nums[0]+nums[1]+nums[-1]-target)
        #print(minv, mind)
        for k in range(len(nums)):
            i = k+1
            j = len(nums)-1
            while i<j:
                diff = nums[k] + nums[i] + nums[j] - target
                #print(k,i,j,diff,mind)
                if diff==0:
                    return target
                else:
                    if abs(diff)<=mind:
                        minv = nums[k] + nums[i] + nums[j]
                        mind = abs(diff)
                        #print(minv, mind)
                    if diff<0:
                        i += 1
                    else: 
                        j -= 1
        return minv

Given an array nums of n integers and an integer target, are there elements abc, and d in nums such that a + b + c + d = target? Find all unique quadruplets in the array which gives the sum of target.

Note:

The solution set must not contain duplicate quadruplets.

Example:

Given array nums = [1, 0, -1, 0, -2, 2], and target = 0.

A solution set is:
[
  [-1,  0, 0, 1],
  [-2, -1, 1, 2],
  [-2,  0, 0, 2]
]

给定一个数组,寻找非重复四元组使其和等于target.

类似于三元组和问题,如果暴力求解时间复杂度为N4.

首先将数组排序,数组变为有序之后。利用两个指针来遍历前两个元素,后面再利用双指针从头尾向中间递进,依次寻找符合条件的组合解,将时间复杂度降为N2logN

class Solution:
    def fourSum(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: List[List[int]]
        """
        nums.sort()
        rr = []
        for k in range(len(nums)):
            if k>0 and nums[k]==nums[k-1]:
                continue
            for m in range(k+1, len(nums)):
                if m>k+1 and nums[m]==nums[m-1]:
                    continue
                i=m+1
                j=len(nums)-1
                while i<j:
                    sum=nums[k]+nums[m]+nums[i]+nums[j]
                    if sum==target:
                        rr.append([nums[k],nums[m],nums[i],nums[j]])
                        while i<j and nums[i]==nums[i+1]:
                            i += 1
                        while i<j and nums[j]==nums[j-1]:
                            j -= 1
                        i += 1
                        j -= 1
                    elif sum<target:
                        i += 1
                    else:
                        j -= 1
        return rr     

去重要考虑四个指针的去重,k,m分别从头向尾遍历,因此去重要考虑每一个元素与前一个元素是否相同,如果相同则直接跳过进行下一个元素遍历;i,j分别从头尾向中间遍历递进,当找到符合条件的元组时,i,j应该继续向中间逼近,直到取到新的不同于上一个值为止,继续进行求和与target的大小判断,即可去重。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值