leetcode刷题记第15题解法(python解析)

题目定义

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

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

示例:

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

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

来源:力扣(LeetCode)
链接: leetcode_15题.

解题

本次使用4种方法,在leetcode上还有更多的方法,只能说真牛逼,真聪明。

1. 暴力解法

使用暴力的方法进行搜索,先定住两个数,然后用0减去前两个数,看有没有值,如果有,添加进结果,然后使用numpy库进行去重

2. 定住两个数然后二分查找第三个

定住两个数,使用二分查找第三个数,然后使用内置库进行去重,注意set不能对多list去重,但是能对tuple进行去重

3. 定住一个数,然后二分查找后两个数

双下标法,极其巧妙,可以多看看

4. 使用python的内置函数

itertools.combinations (对数据进行自由组合,找出所有的组合)

frozenset

>>> frozenset((-1, 0, -1))
frozenset({-1, 0})

===================================================

实现

// An highlighted block

class Solution:
    def threeSum(self, nums):
        """
        # 1.暴力枚举法  n^3   超时了  严重超时
        """
        if len(nums) < 3:
            return []
        list_end = []
        for a in range(len(nums)):
            for b in range(a + 1, len(nums)):
                c = 0 - nums[a] - nums[b]
                if c in nums[b + 1:]:
                    list_end.append(sorted([nums[a], nums[b], c]))

        if len(list_end) < 1:
            return []
        import numpy as np
        list_end = np.array(list_end)

        list_end = np.unique(list_end, axis=0)
        return list_end.tolist()

    def threeSum_1(self, nums):
        """
        # 二分查找 定住两个数 查第三个   n^2*logn
        """
        nums.sort()  # 先排序
        ret = []  # 最终值
        n = len(nums)
        for i in range(0, n):
            for j in range(i + 1, n):  # 先定住两个
                d = 0 - (nums[j] + nums[i])  # 找到第三个

                l = 0  # 最左
                r = n - 1  # 最右
                p = -1
                while l <= r:
                    m = (l + r) >> 1  # 取中值
                    if nums[m] == d:
                        p = m
                        break
                    elif nums[m] > d:  # 如果 中间的值大于  d  这说明在左边
                        r = m - 1
                    elif nums[m] < d:  # 如果 中间的值小于  d  这说明在右边
                        l = m + 1
                if p != -1 and p != i and p != j:
                    ret.append( (nums[i], nums[j], nums[p]))

        nn = len(ret)
        for i in range(0, nn):
            ret[i] = list(ret[i])
            ret[i].sort()
            ret[i] = tuple(ret[i])
        ret = list(set(ret))
        return ret



    def threeSum_2(self, nums):
        '''
        # 同样是二分法进行查找  但是非常的巧妙  仔细理解一下
        '''
        nums.sort()
        res = []

        for i in range(len(nums)):
            if i == 0 or nums[i] > nums[i - 1]:   # 如果是刚开始  或者 排完序之后下一个数字大于前一个数字
                l = i + 1  # 左
                r = len(nums) - 1  #右
                while l < r:
                    s = nums[i] + nums[l] + nums[r]   # s= 当前数值 + 左边的数值 + 右边的数值
                    if s == 0:
                        res.append([nums[i], nums[l], nums[r]])   # 如果正好 等于 0
                        l += 1
                        r -= 1
                        while l < r and nums[l] == nums[l - 1]:  # 执行的去重操作  如果左边的的数都相同就去重
                            l += 1
                        while r > l and nums[r] == nums[r + 1]:  # 执行的去重操作  如果右边的的数都相同就去重
                            r -= 1
                    elif s > 0:
                        r -= 1
                    else:
                        l += 1
        return res

    def threeSum_3(self, nums):
        import itertools
        ts, bs = [i for i in set(list(itertools.combinations(nums, 3))) if sum(i) == 0], {}  #  求出所有的组合  然后  set 去重  判断等于0 的加入ts
        for i in ts:
            '''
            >>frozenset((-1, 0, -1))
            frozenset({-1, 0})
            输入 [-1, 0, 1, 2, -1, -4]
            输出{frozenset({2, -1}): (-1, 2, -1), frozenset({0, 1, -1}): (-1, 0, 1)}
            '''
            bs.update({frozenset(i): i}) if frozenset(i) not in list(bs.keys()) else 0    # 将字典的key作为 frozenset存储

        return list(bs.values())



print(Solution().threeSum_3( [-1, 0, 1, 2, -1, -4] ))

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值