Leetcode15 第十五题

Leetcode15 第十五题

先来题诗:

一顿操作猛如虎,点击提交超时了。

二话不说翻题解,评论区里全人才。

反反复复终得道,再次尝试却报错。

行行检查字字改,击败用户百分五。

解题思路:

这道题真的让爷服了,一眼看去很简单,直接暴力解得了,结果是三个循环,时间复杂度是O(n^3),这也太大了,先扔进去看看,结果超时。

事实上拿三个循环暴力解,还需要解决一个问题,那就是如何避免结果重复的三元组。看了下官方解决办法是通过哈希表去解决,但是消耗了大量的内存空间。和大佬同学讨论了一下之后,觉得可以先将所有的三元组内部排序,接着将其转化成元组,元组作为列表的元素是可以再次排序的(震惊!这个知识点我居然还不知道),这样子每个三元组外部是排好序,内部也是排好序的,相邻的两个两两比较就可以,相同就删除后面那个,继续遍历,这样判断的最大时间复杂度是在排序上,最多O(n^2)一般O(nlogn).

为了优化(不超时),我们需要变成两个循环。

根据题目:找到三元组不能重复

1、可以想到,如果先排序(能保证重复出现的数字在一起,并且时间复杂度为O(nlogn),没啥影响)

2、可以在第二重循环的枚举中找到不小于当前第一重循环的枚举元素

3、和第三重循环同理,找到不小于第二重循环的枚举元素

那么能想到了排序,但是本质上还是三重循环,那么时间复杂度还是O(N^3),继续优化,将下面的两重循环变成一重循环:

可以发现我们是固定了第一个数然后去找其他两个数的,那么可以将后面两个数看成一个数,那么问题就变成了‘’在有序数组中从[i+1, len-1]这个范围内找到一个符合要求的数,那么就变成了双指针问题‘’,而这个数的值不再是mid,而是两个边界left和right的和。而指针的移动条件就是:如果当前的sum值太大,那么右指针就移动;如果sum太小,那么左指针就移动;如果值正好,那么就是当前值,并且左指针右移,右指针左移(因为是找到所有满足的解);循环的结束条件就是左右指针相遇 而双指针情况下,第二三重循环就从O(N^2)变成O(N)。同时为了保证因为前后数字重复最后构成的三元组一致,进行一个是否再列表中的判断。

代码

class Solution:
    def threeSum(self, nums: List[int]) -> List[List[int]]:
        list=[]
        nums.sort()
        for i in range(len(nums)):
            j=i+1
            k=len(nums)-1
            while j<k:
                a=nums[i]
                b=nums[j]
                c=nums[k]
                if b+c>-a:
                    k-=1
                elif b+c<-a:
                    j+=1
                elif b+c==-a:
                    num=[a,b,c]
                    if num not in list:
                        list.append(num)
                    k-=1
                    j+=1
        return list

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值