LeetCode 算法题库【15】——三数之和

三数之和

题目描述:

timu

解题思路:
  • 第一种:对于这道题,我们用的是排序 + 双指针的解法。开始我们有个比较好的思路,就是我们可以先对数组进行从小到大排序,然后我们容易发现,要使得三个数相加为0,第一个数必须要是小于等于零,如果大于零了,那后面的数字也是大于零的,这样相加肯定是不可能等于0的。所以我们只需要从小开始找,直到发现第一个数开始大于零了,就可以返回这些三元组了。下一个就是我们在头尾设置双指针LeftRight,然后找到满足条件的三元组放进新定义的数组dic中。还有比较重要的点是去重,这里有两处去重,一处是第一个数,还有一处是双指针处,都要保证当前用的数字不能和前一个相同。
class Solution:
    def threeSum(self, nums: List[int]) -> List[List[int]]:
        lens = len(nums)
        dic = []
        nums.sort()
        if lens < 3:
            return []
        else:
            for i in range(lens):
                if nums[i] <= 0:
                    if i > 0 and nums[i] == nums[i-1]:
                        continue
                    Left = i + 1
                    Right = lens - 1
                    while Left < Right:
                        if nums[i] + nums[Left] == -nums[Right]:
                            dic.append([nums[i], nums[Left], nums[Right]])
                            while Left < Right and nums[Left] == nums[Left + 1]:
                                Left += 1
                            while Left < Right and nums[Right] == nums[Right - 1]:
                                Right -= 1
                            Left += 1
                            Right -= 1
                        elif nums[i] + nums[Left] < -nums[Right]:
                            Left += 1
                        else:
                            Right -= 1
                else:
                    return dic
        return dic

1
类似方法,减少代码量。

class Solution:
    def threeSum(self, nums: List[int]) -> List[List[int]]:
        lens = len(nums)
        nums.sort()
        Res = []
        for i in range(lens-2):
            if nums[i] > 0:
                break
            if i > 0 and nums[i] == nums[i-1]:
                continue
            j = i + 1
            h = lens - 1
            while j < h:
                if nums[i] + nums[j] == -nums[h]:
                    Res.append([nums[i], nums[j], nums[h]])
                    h -= 1
                    j += 1
                    while j < h and nums[j] == nums[j-1]:
                        j += 1
                    while j < h and nums[h] == nums[h+1]:
                        h -= 1
                elif nums[i] + nums[j] > -nums[h]:
                    h -= 1
                    while j < h and nums[h] == nums[h+1]:
                        h -= 1
                else:
                    j += 1
                    while j < h and nums[j] == nums[j-1]:
                        j += 1
        return Res
  • 第二种:我看了看一些大佬的解法,下面用哈希表法来解决这个问题。同理一开始也是先对数组进行排序, 遍历数组如果遇到与前一个元素相同的情况,就直接跳过。这里比较巧妙的就是,把三数之和问题简化成了两数之和问题,这里一开始就把每个元素的相反数都存入哈希表中,然后就只需要看两数之和是否在哈希表中即可。时间复杂度为O(n^2) 。
class Solution:
    def threeSum(self, nums: List[int]) -> List[List[int]]:
        Res = []
        nums.sort()
        if len(nums) < 3:
            return Res
        target_hash = {-x: i for i, x in enumerate(nums)}
        res_hash = {}
        for i, Front in enumerate(nums):
            if i > 0 and Front == nums[i - 1]:
                continue
            for j, Back in enumerate(nums[i + 1:]):
                if Front + Back in target_hash:
                    target_index = target_hash[Front + Back]
                    if target_index == i or target_index == i + j + 1:
                        continue
                    dic = sorted([Front, Back, nums[target_index]])
                    key = ",".join([str(x) for x in dic])
                    if key not in res_hash:
                        Res.append(dic)
                        res_hash[key] = True
        return Res

2

  • 第三种:这个方法用到了一个bisect模块,用二分法来解决该问题就运行速度快了很多。(以后再补充)
class Solution:
    def threeSum(self, nums: List[int]) -> List[List[int]]:
        Res = []
        dic = {}
        for a in nums:
            dic[a] = dic.get(a, 0) + 1
        nums = sorted(dic)
        for b, temp in enumerate(nums):
            if dic[temp] > 1:
                if temp != 0:
                    if -temp * 2 in dic:
                        Res.append([temp, temp, -2 * temp])
                else:
                    if dic[temp] > 2:
                        Res.append([0, 0, 0])
            if temp < 0:
                two_sum = -temp
                left = bisect.bisect_left(nums, (two_sum - nums[-1]), b + 1)
                for i in nums[left: bisect.bisect_right(nums, (two_sum // 2), left)]:
                    j = two_sum - i
                    if j != i and j in dic:
                        Res.append([temp, i, j])
        return Res

3

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值