[解题笔记] LeetCode 7月挑战题目之8

3Sum

这是我第一次参加 LeetCode (力扣) 的每月挑战题组,希望留下点笔记,大家可以参考和互相讨论。😃

第八天问:

给你一个有 n 个整数的数列 nums,其中会不会有三个元素 a, b, c,相加之后为零?请在这数列中,找出所有能够相加为零 (组合不能重复) 的三元素数列

题目与例子 (引用自LeetCode):

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.

Given array nums = [-1, 0, 1, 2, -1, -4],

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

提示:

  1. 现在我们要找的是三个相加为零的数,但如果假设我们先固定一个数x,那就可以变成 2sum 问题。
  2. 2sum 问题上,如果假设我们先固定一个数x,那就需要扫一次整个数列找 y = value - x (value 是一个input parameter)。只是,能加速这算法吗?
  3. 2sum 的第二个思路是:在不改变数列的前提下,或许能考虑用哈希表 (haspmap) 来加快计算?

解题思路:

2sum 题目容易算,是因为只有两个数,最简单粗暴的就是 double for-loop 迭代一下就完事了;但这个直接迭代是会超时报錯的。以下这段代因为时间复杂度太高,因为time limit exceeded又被打回了。

失败代码 (时间复杂度:O(n3 + n log n))

class Solution:
    def threeSum(self, nums: List[int]) -> List[List[int]]:
        result = []
        if len(nums) < 3:
            return result
        for i in range(len(nums)):
            num1 = nums[i]
            for j in range(i + 1, len(nums)):
                num2 = nums[j]
                k = j + 1
                while k < len(nums):
                    num3 = nums[k]
                    if num2 + num3 == -1 * num1:
                        if sorted([num1, num2, num3]) not in result:
                            result.append(sorted([num1, num2, num3]))
                    k += 1
        result.sort()
        return result

想了一阵子,试了几遍,还是沒搞出来🤯。沒辦法,只好上网找资料。在 leetcode 的讨论区中,看到了一篇文章 (文章来源请看参考资料) 用了一个方法跟我上面有点类似,一开始也是从迭代整个数列 (for-loop) 入手,然后后面就不一样了:

  1. 第一个 if-clase 是用来跳过已经做过的迭代,避免重复计算 (因为条件nums[i] == nums[i - 1]代表现在的nums值跟上一次一样,那上一個循环必定已包括这个循环会做的计算)
  2. begend分別是现值在 数列的位置的下一位数数列最后一位数
  3. 最后,用 while-loop 做迭代,只要 nums[beg] + nums[end] 现值的负数,就可以加到答案列上。

这个方法好处是使用了 if-clausewhile-loop 两个方法既可以減少时间复杂度,又能同步降低实际所需时间。

引用代码 (时间复杂度: O(n log n + n2))

class Solution:
    def threeSum(self, nums: List[int]) -> List[List[int]]:
        nums.sort()
        n = len(nums) 
        result = []
        for i in range(n):
            if i > 0 and nums[i] == nums[i - 1]: 
                continue
            target = -nums[i]
            beg = i + 1
            end = n - 1
            while beg < end:
                if nums[beg] + nums[end] < target:
                    beg += 1
                elif nums[beg] + nums[end] > target:
                    end -= 1
                else:
                    result.append((nums[i], nums[beg], nums[end]))
                    beg += 1
                    end -= 1
        return set(result)

Reference/参考资料:

https://leetcode.com/problems/3sum/discuss/725581/Python-2-Pointers-O(n2)-solution-explained (代码引用来源)
https://www.cnblogs.com/grandyang/p/4481576.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值