【leetcode】15. 三数之和 18 四个数之和 & 任意个数的和 解题思路 # faster than 89.13%

博客围绕LeetCode中三数之和问题展开,题目要求在给定整数数组中找出所有和为0且不重复的三元组。介绍了两种解题思路,一是暴力解法,时间复杂度O(n3);二是对撞指针法,时间复杂度O(n2),并给出Python代码实现,对比显示后者耗时远低于前者。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

四个数之和 & 任意个数的和 转博主下一篇博客链接

一、 题目要求

给定一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?找出所有满足条件且不重复的三元组。
注意:答案中不可以包含重复的三元组。
例如, 给定数组 nums = [-1, 0, 1, 2, -1, -4],
满足要求的三元组集合为:
[
[-1, 0, 1],
[-1, -1, 2]
]

二、 解题思路与python实现

2.1 暴力解法(时间复杂度O(n3))

对于leetcode中任何一道题目,在没有思路的情况下都可以尝试一下暴力解法,虽然时间复杂度会很高, 但是也不妨是一种解题思路。并且在你为暴力解法编写代码的时候说不定就有了新的优化解法思路。

在这道题目里,我们不难想到三重循环遍历这个数组,对于每个组合验证一下是否符合sum==0这个条件, 如果符合那么就添加到结果数组里,这里需要注意组合存在重复的情况。对于暴力解法这里就不详细解读了,相信大家都看得明白。
python代码实现:

class Solution:
    def threeSum(self, nums):
        """
        :type nums: List[int]
        :rtype: List[List[int]]
        """
        from collections import Counter
        k = []
        result = []
        for i, a in enumerate(nums):
            for j, b in enumerate(nums[i + 1:]):
                for _, c in enumerate(nums[j + i + 2:]):
                    if a + b + c == 0 and Counter([a, b, c]) not in k:
                        k.append(Counter([a, b, c]))
        for i in k:
            result.append(list(i.elements()))
        return result

2.2 对撞指针 (时间复杂度O(n2))

相信大家踩过leetcode第一题 两个数的和 的坑,并且对它有了很好的理解(具体解题思路请参考链接,这里不再累述)。当看到这一题时,肯定会想到两个数的和的解题思路,其实这样是对的。

这里对于三元组,我们可以先遍历一次数组,这样就相当于已知了sum和其中一个数, 那么另外两个数的和就确定了,此时对于另外两个数的求和是不是就和两个数的和一样了呢?所以,这里我们就可以用两个数的和的方法使用双指针求解了,当然你也可以使用其他你喜欢的算法去求解。

当然这里对于两个数的和,我们使用双指针首先就需要求这个数组排序。nums.sort()
具体python实现:

def threeSum(self, nums):
    res = []
    nums.sort()
    for i in xrange(len(nums)-2):
    	if nums[i] >  0: break  # sum== 0 ,三元组中必然有一个小于等于0 的数 ,如果最小值>0 那么可以跳出循环了
        if i > 0 and nums[i] == nums[i-1]:  #*排序后相邻两数如果相等,则跳出当前循环继续下一次循环相同的数只需要计算一次
            continue
        l, r = i+1, len(nums)-1
        while l < r:
            s = nums[i] + nums[l] + nums[r]
            if s < 0:
                l +=1 
            elif s > 0:
                r -= 1
            else:
                res.append((nums[i], nums[l], nums[r]))   # 把结果加入数组中
                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 # 没有相等则j+1,k-1,缩小范围
    return res
  

耗时对比:
1.暴力法 347.76ms
2.优化方案 2.64ms
话不多说,感受下这个天壤之别。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值