Leetcode 15 3Sum

Leetcode 15 3Sum

题目描述

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.

Example:

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

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

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/3sum
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

题目解析
  • 思路一:暴力穷举所有的可能性,最后做一个去重处理,但这种算法时间复杂度为 O ( n 3 ) O(n^3) O(n3),显然不能作为我们的解决方案
class Solution:
    def threeSum(self, nums: List[int]) -> List[List[int]]:
        if nums is None or len(nums) < 3:
            return []
        length = len(nums)
        nums.sort()
        result = []
        for i in range(0, length):
            for j in range(i + 1, length):
                for k in range(j + 1, length):
                    if nums[i] + nums[j] + nums[k] == 0:
                        result.append([nums[i], nums[j], nums[k]])                     
        # 去重
        result_temp = []
        for item in result:
            if item not in result_temp:
                result_temp.append(item)
        return result_temp

注意:[[],[],[]]这样的列表是无法转换为set来去重的。!

待解决:

  1. 列表中每个元素不是唯一的
  2. 重复,顺序不同的重复

O ( n 3 ) O(n^3) O(n3)时间复杂度太高,我们可以稍作改动,得到一个时间复杂度为 O ( n 2 ) O(n^2) O(n2)的算法:

class Solution:
    def threeSum(self, nums: List[int]) -> List[List[int]]:
        if nums is None or len(nums) < 3:
            return []
        length = len(nums)
        nums.sort()
        result = []
        for i in range(0, length):
            for j in range(i + 1, length):
                temp = -1 * (nums[i] + nums[j])
                if temp in nums[j+1:]:
                    result.append([nums[i], nums[j], temp])
        # 去重
        result_temp = []
        for item in result:
            if item not in result_temp:
                result_temp.append(item)
        return result_temp

遍历列表中的每个元素,利用双指针在该元素的后面查找使三数之和为0的组合,时间复杂度为 O ( N 2 ) O(N^2) O(N2),但是还是超时。

class Solution:
    def threeSum(self, nums: List[int]) -> List[List[int]]:
        if nums is None or len(nums) < 3:
            return []
        length = len(nums)
        nums.sort()
        result = []
        for i in range(length):
            left = i + 1
            right = length - 1
            while left < right:
                sum = nums[i] + nums[left] + nums[right]
                if sum == 0:
                    result.append([nums[i], nums[left], nums[right]])
                    left += 1
                    right -= 1
                elif sum < 0:
                    left += 1
                else: right -= 1
        # 去重
        result_temp = []
        for item in result:
            if item not in result_temp:
                result_temp.append(item)
        return result_temp                    

上述代码有很多可以优化的地方,通过一些边界条件的判断可以省去很多不必要的操作,从而提高效率。

class Solution:
    def threeSum(self, nums: List[int]) -> List[List[int]]:
        if nums is None or len(nums) < 3:
            return []
        length = len(nums)
        nums.sort()
        result = []
        for i in range(length - 2): # 后续元素少于三个,不用判断
            if nums[i] > 0: # 首元素大于0,三数之和必定大于0
                break
            if nums[i] > 0 and nums[i] == nums[i - 1]: # 避免重复
                continue
            l = i + 1
            r = length - 1
            while l < r:
                sum = nums[i] + nums[l] + nums[r]
                if sum == 0:
                    result.append([nums[i], nums[l], nums[r]])
                    l += 1
                    r -= 1
                    while l < r and nums[l] == nums[l - 1]: l += 1 # 去重
                    while l < r and nums[r] == nums[i + 1]: r -= 1 # 去重
                elif sum < 0:
                    l += 1
                    while l < r and nums[l] == nums[l - 1]: l += 1 # 去重
                else: 
                    r -= 1
                    while l < r and nums[r] == nums[r + 1]: r -= 1 # 去重
        return result

注意特殊用例:[0, 0, 0, 0]、[0, 0, 0]

从上面的解题过程中我们可以看到,暴力法时间复杂度高,但不用判断很多边界条件,而双指针法通过双指针以及增加很多边界条件的判断,省去了很多不必要的操作,从而使算法的效率提高。

感觉常规解题时,总是先有一个解决方案,接着针对各种用例,以及原解决方案存在的问题,一步步添加边界条件、转化思路去优化我们的解决方案,从而提高算法的效率,得到一种相对较好的解决方案。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值