(python刷题)leetcode 第15题:三数之和

题目在leetcode上的链接为:
https://leetcode-cn.com/problems/3sum/

题目描述
在这里插入图片描述

解题思路
首先想到的是使用暴力法解题,使用三重循环遍历数组,然后判断三个数相加是否为0并去重即可,时间复杂度为 o(n3)。为了降低时间复杂度,我们可以将数组排序后再使用双指针的解法。
具体步骤为:

  • 首先如果 nums 为 None,或者 nums 长度小于3,那么返回空列表
  • 将 nums 按照从小到大进行排序
  • 使用变量 i 循环遍历 nums:
    • 令左指针 left 为 i+1,右指针 right 为 len(nums)-1
    • 如果 nums[i]>0,说明三个数中最小的都大于0,那么之后就不存在三个数之和等于0了,直接返回结果
    • 如果 nums[i]=nums[i-1],说明前一步中已经考虑了这一步可能存在的三个数的结果,那么就不执行之后的代码,以此进行去重操作
    • 以 left<right 作为判断条件进入循环:
      • 如果 nums[i]+nums[left]+nums[right] 等于0:
        • 将找到的三个数添加到结果中
        • 循环判断如果左右指针位置的数等于它门下一个位置的数时,就将指针移到下一个位置进行去重操作
        • 将左右指针都移到下一个位置重新找下一个可能的结果
      • 如果 nums[i]+nums[left]+nums[right] 小于0,说明太小了,则将左指针向右移动一步
      • 如果 nums[i]+nums[left]+nums[right] 大于0,说明太大了,则将右指针向左移动一步

上述解法中容易出错的就是去重操作,需要仔细注意下两方面的去重操作,一个是遍历 i 的过程中可能出现重复,另一个是在固定 i 时,左右指针遍历 i 之后的数可能出现重复:
(1)当 nums[i]=nums[i-1] 时,由于在 i-1 的步骤中左右指针进行遍历操作时,已经遍历过了 i-1 右边的数了,因此在 i 的位置处找到的符合条件的三个数肯定已经包含在 i-1 位置处找到的结果中,因此要进行去重操作。
(2)另外就是在之后的 nums[i]+nums[left]+nums[right] 等于0 时,这个时候 i 是固定的,如果 nums[left]=num[left+1],说明左指针下一个位置的结果与当前的结果重复;同理如果 nums[right]=num[right-1],说明右指针下一个位置的结果与当前的结果重复,需要进行去重操作

复杂度分析:
排序操作的时间复杂度为 o(nlog(n)),两重循环的复杂度为 o(n2),由于这两步操作是顺序执行,所以总的时间复杂度为 o(nlog(n))+o(n2),即为 o(n2)。
由于只需要常数级的存储空间,所以空间复杂度为 o(1)

python代码:

class Solution:
    def threeSum(self, nums: List[int]) -> List[List[int]]:
        if not nums or len(nums) < 3:
            return []
        nums.sort()
        res = []
        for i in range(len(nums)):
            if nums[i] > 0:
                return res
            if i > 0 and nums[i] == nums[i - 1]:
                continue
            left = i + 1
            right = len(nums) - 1
            while left < right:
                if nums[i] + nums[left] + nums[right] == 0:
                    res.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] < 0:
                    left += 1
                else:
                    right -= 1
        return res
发布了37 篇原创文章 · 获赞 6 · 访问量 5385

猜你喜欢

转载自blog.csdn.net/qq_37891889/article/details/104325528