LeetCode之二数三数四数之和

题号1:两数之和

给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。 你可以假设每种输入只会对应一个答案。但是,你不能重复利用这个数组中同样的元素。 示例

给定 nums = [2, 7, 11, 15], target = 9
因为 nums[0] + nums[1] = 2 + 7 = 9 所以返回 [0, 1]

  • 法一

这题最简单的办法无非就是暴力解法,两个循环就解决,时间复杂度是O(n2)。太过简单,我也懒得贴代码了。

  • 法二

双指针法:L指针指向数组头部,R指针指向数组尾部。
L+R==Target时,直接返回
L+R<Target时,L指针左移
L+R>Target时,R指针右移
这种方法的时间复杂度为O(n)

class Solution:
    def twoSum(self, nums: 'List[int]', target: 'int') -> 'List[int]':
    
        l=0
        r=len(nums)-1
        while(l<r):
            if nums[l]+nums[r]==target:
                return [l,r]
            elif nums[l]+nums[r]<target:
                l+=1
            else:
                r-=1

但是请注意:这种方法只能在数组已经排序好的情况下使用,要AC这题的话,我们最好还是换种方法

  • 法三

字典法,时间复杂度同样为O(n)。创建一个空字典。对数组进行遍历,若Target减去当前项存在于字典中,通过key获得value,直接返回[value和当前项即可]。若不存在,把当前项存入字典中
废话少说,上代码

class Solution:
    def twoSum(self, nums: 'List[int]', target: 'int') -> 'List[int]':
        dic={}
        for index, value in enumerate(nums):
            want=target-value
            if want in dic:
                return [dic[want],index]
            else:
                dic[value]=index
        return []

题号15:三数之和

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

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

例如, 给定数组 nums = [-1, 0, 1, 2, -1, -4],
满足要求的三元组集合为:
[
[-1, 0, 1],
[-1, -1, 2]
]

  • 使用上一题的双指针法即可解,代码如下
class Solution(object):
    def threeSum(self, nums):
        """
        :type nums: List[int]
        :rtype: List[List[int]]
        """
        triple=[]
        nums.sort()
        for i in range(len(nums)-2):
            j=i+1
            k=len(nums)-1
            while(j<k):
                if nums[j]+nums[k]+nums[i]==0:
                    a=[nums[i],nums[j],nums[k]]
                    if a not in triple:
                        triple.append(a)
                    j+=1
                elif nums[j]+nums[k]+nums[i]<0:
                    j+=1
                else:
                    k-=1
        return triple

时间复杂度为O(n2),虽然一遍ac了但是达到了8300ms仅击败零点几的用户,很蛋疼啊,一定有更好的办法

对其进行改进,代码如下

class Solution:
    def threeSum(self, nums: 'List[int]') -> 'List[List[int]]':
        target=0
        dic={}
        triple=[]
        if len(nums)<3:
            return []
        for i in nums:
            if i in dic:
                dic[i] += 1
            else:
                dic[i] = 1
        nums=[i for i in dic]
        nums.sort()
        if target%3==0:
            if  int(target/3)in dic:
                if dic[int(target/3)]>2:
                    fuck=int(target/3)
                    triple.append([fuck,fuck,fuck])
        for i in range(len(nums)):
            j=i+1
            k=len(nums)-1
            want=target-nums[i]
            if want%2==0 and nums[i]!=int(want/2):
                if  int(want/2) in dic:
                    if dic[int(want/2)]>1:
                        a=[nums[i],int(want/2),int(want/2)]
                        a.sort()
                        triple.append(a)
            while(j<k):
                if nums[j]+nums[k]==want:
                    triple.append([nums[i],nums[j],nums[k]])
                    j+=1
                elif nums[j]+nums[k]<want:
                    j+=1
                elif nums[j]+nums[k]>want:
                    k-=1
        return triple

优化至1300ms,好过百分之三十四的同学,一定还有更好的办法,再次优化如下

class Solution:
    def threeSum(self, nums: 'List[int]') -> 'List[List[int]]':
        dic={}
        triple=[]
        for i in nums:
            if i in dic:
                dic[i] += 1
            else:
                dic[i] = 1

        pos = [i for i in dic if i>0]
        neg = [i for i in dic if i<0]
        if 0 in dic and dic[0]>2:
            triple.append([0,0,0])
        for i in neg:
            for j in pos:
                want=-i-j
                if want in dic:
                    if (want==i or want==j) and dic[want]>1:
                        triple.append([i,want,j])
                    elif i<want<j:
                        triple.append([i,want,j])
        return triple

击败了98.37的用户,应该极限就在这里了。
题号16:最接近的三数之和解法类似,不赘述
题号18:四数之和

给定一个包含 n 个整数的数组 nums 和一个目标值 target,判断 nums 中是否存在四个元素 a,b,c 和 d ,使得 a +
b + c + d 的值与 target 相等?找出所有满足条件且不重复的四元组。

注意:

答案中不可以包含重复的四元组。

示例:给定数组 nums = [1, 0, -1, 0, -2, 2],和 target = 0。
满足要求的四元组集合为: [ [-1, 0, 0, 1], [-2, -1, 1, 2], [-2, 0, 0, 2] ]

其实把上题的代码稍作修改即可ac,如下:

class Solution:
    def threeSum(self, nums: 'List[int]',target:'int') -> 'List[List[int]]':
        dic={}
        triple=[]
        if len(nums)<3:
            return []
        for i in nums:
            if i in dic:
                dic[i] += 1
            else:
                dic[i] = 1
        nums=[i for i in dic]
        nums.sort()
        if target%3==0:
            if  int(target/3)in dic:
                if dic[int(target/3)]>2:
                    fuck=int(target/3)
                    triple.append([fuck,fuck,fuck])
        for i in range(len(nums)):
            j=i+1
            k=len(nums)-1
            want=target-nums[i]
            if want%2==0 and nums[i]!=int(want/2):
                if  int(want/2) in dic:
                    if dic[int(want/2)]>1:
                        a=[nums[i],int(want/2),int(want/2)]
                        a.sort()
                        triple.append(a)
            while(j<k):
                if nums[j]+nums[k]==want:
                    triple.append([nums[i],nums[j],nums[k]])
                    j+=1
                elif nums[j]+nums[k]<want:
                    j+=1
                elif nums[j]+nums[k]>want:
                    k-=1
        return triple  
    def fourSum(self, nums: 'List[int]', target: 'int') -> 'List[List[int]]':
        if len(nums)<4:
            return []
        nums.sort()
        joke=[]
        i=0
        while(i<len(nums)-1):
            #print(nums[i+1:])
            tree= self.threeSum(nums[i+1:],target-nums[i])
            for k in tree:
                new=[nums[i]]
                new+=k
                joke.append(new)
            while(nums[i]==nums[i+1] and i+1<len(nums)-1):
                i+=1
            i+=1
        return joke
            

仅击败10.98的用户,当然可以再优化,但是这和前几题的原理基本相同,懒得弄了。就到这吧

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值