LeetCode算法题之15.3Sum(medium)

题目描述:
Given an array nums of n integers, are there elements a, b, c 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,且这三个数的组合不可以重复,最后返回一个列表
  • 首先想到确实是可以将数组中的所有不同的三个数的组合全部找到,依次判断等于0否,实践证明,会超时,时间复杂度会太大,不只是这种三层循环会超时,就连先找出两个数的所有组合,再去找第三个数,这种方式,同样超时,详见代码1
  • 当前网络上较流传的一种思路是,只遍历一次,设置两个另外的变量b,c,使每次遍历到一个数时,内部作b,c的循环,把数找全,而且不重,见图片,一看便知,此种思路,见代码2,3

说明:此图片来源于一位CSDN优秀博主的文章,此博主个人主页地址:https://me.csdn.net/weixin_41463193

如图所示,a即为每次遍历的元素,b,c为新设置的变量,只因为事先进行了数组排序,三个数相加,如果小于0,则只能右移,往大的数方向去寻找能够加和为0的数,同理,小于0的话,道理一样,结合代码,一看便知

少废话,上代码1:

"""
Time Limit Exceeded
"""
class Solution:
    def threeSum(self, nums):
        lt = []

        for i in range(len(nums)-1):
            for j in range(i+1, len(nums)):
                n = nums[i] + nums[j]
                if -n in nums and nums.index(-n) != i and nums.index(-n) != j:
                    m = sorted([nums[i], nums[j], -n])
                    if len(lt) == 0:
                        lt.append(m)
                    if len(lt) > 0 and m not in lt:
                        lt.append(m)

        return lt

代码2:

class Solution:
    def threeSum(self, nums):
        #给数组由小到大排序,既方便寻找数,又方便后续的去重操作
        nums = sorted(nums)
        lt = []

        for i in range(len(nums)-2):
            # 如遇到相同的数,没必要再进行重复的操作,直接跳过
            if i > 0 and nums[i] == nums[i - 1]:
                continue
            b = i + 1
            c = len(nums) - 1
            while b < c:#设置b,c不相遇的条件
                if nums[i] + nums[b] + nums[c] < 0:#说明这三个数小,需使其中一个数据变大,也就是b右移
                    b += 1#因为已经是排好顺序的数组,b向右变大数值
                elif nums[i] + nums[b] + nums[c] > 0:#同理
                    c -= 1
                else:
                    n = [nums[i], nums[b], nums[c]]
                    lt.append(n)
                    # 以下两行,去除索引b和索引c的下一个元素是相同的数的情况,
                    # 也是将总体lt去除相同元素的作用
                    while (b < c and nums[b] == nums[b + 1]):#说明向右移动一个数后,那个数与原值相同
                        b += 1#继续移动
                    while (b < c and nums[c] == nums[c - 1]):#同理
                        c -= 1
                    #将索引固定到那个新的数
                    b += 1
                    c -= 1

        return lt

时间空间复杂度:

  • Runtime: 1124 ms, faster than 40.69% of Python3 online submissions for 3Sum.
  • Memory Usage: 17.2 MB, less than 24.28% of Python3 online submissions for 3Sum

代码3:
(利用集合,来源于LeetCode上同僚的代码,本人稍加解释,共同学习)

class Solution:
    def threeSum(self, nums):
        #同样的想法,不过利用Python的集合结构,因为集合本身的性质决定,不允许有重复元素存在
        triplets = set()
        nums.sort()

        for i in range(len(nums) - 2):
            if nums[i] > 0:#说明排序之后的最小的数,如果都大于0,则后面更大于0,直接结束
                break
            if i > 0 and nums[i] == nums[i - 1]:#跳过相同的数,避免重复操作
                continue

            #思路相同,全部是两边向中间靠近,遍历整个数组
            l = i + 1
            r = len(nums) - 1
            while l < r:
                total = nums[i] + nums[l] + nums[r]
                if total > 0:
                    r -= 1
                elif total < 0:
                    l += 1
                else:
                    triplets.add((nums[i], nums[l], nums[r]))#利用了集合的性质,如有重复元素,自动删除,保证单一
                    l += 1
                    r -= 1

        return [list(t) for t in triplets]#最后转换成列表,符合题目要求的输出

时间空间复杂度:

  • Runtime: 716 ms, faster than 84.82% of Python3 online submissions for 3Sum.
  • Memory Usage: 17 MB, less than 25.71% of Python3 online submissions for 3Sum.
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值