【20190624】【每天一道算法题】三数之和(双指针)

问题

给定一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?找出所有满足条件且不重复的三元组。

注意:答案中不可以包含重复的三元组。

例如, 给定数组 nums = [-1, 0, 1, 2, -1, -4],满足要求的三元组集合为:


思路及解答

# 方法一:暴力法。
# 时间复杂度:O(n^3)。超时。
# 加入sorted函数是为了结果中不出现重复的结果。
class Solution:
    def threeSum(self, nums: List[int]) -> List[List[int]]:
        l = len(nums)
        result = []
        for i in range(l-2):
            for j in range(i+1, l-1):
                for m in range(j+1, l):
                    if nums[i]+nums[j]+nums[m] == 0 and sorted([nums[i], nums[j], nums[m]]) not in result:
                        result.append(sorted([nums[i], nums[j], nums[m]]))
        return result
		

# 方法二:哈希表。先固定两个数(两层循环),再找第三个满足条件的值,方法类似于【Two Sum】那道题。
# 运行正确,但提交结果超时。
# 时间复杂度:O(n^2)
class Solution:
    def threeSum(self, nums: List[int]) -> List[List[int]]:
        l = len(nums)
        result =[]
        hashmap = {}
        while(l):   # 这里是小写字母l,不是一。即while(len(nums))。为了防止数组为空下面的hashmap[nums[0]] = 0 出现错误!
            hashmap[nums[0]] = 0
            for index1, num1 in enumerate(nums):
                for index2, num2 in enumerate(nums[index1+1:l], index1 + 1) :
                    if -(num1+num2) in hashmap and hashmap[-(num1+num2)] != index1 and hashmap[-(num1+num2)] != index2:
                        if sorted([num1, num2, -(num1+num2)]) not in result:
                            result.append(sorted([num1, num2, -(num1+num2)]))
                    hashmap[num2] = index2
            return result
        return []
		
		
# 方法三:双指针。选择一个C位,我选的是第二个元素(不为空的前提下),然后每次大循环都low=0,high=length-1。每大循环一次变换一次C位(加一)
# 运行正确,但提交结果超时。
# 时间复杂度:O(n^2)
class Solution:
    def threeSum(self, nums: List[int]) -> List[List[int]]:
        result = []
        nums.sort()
        length = len(nums)
        indexC = 1
        while(indexC < length - 1):
            low, high = 0, length-1
            while(low < indexC and high > indexC):
                if nums[low] + nums[high] == -nums[indexC]:
                    if [nums[low], nums[indexC], nums[high]] not in result:
                        result.append([nums[low], nums[indexC], nums[high]])
                    low, high = low + 1, high - 1 
                elif nums[low] + nums[high] > -nums[indexC]:
                    high = high - 1
                else:
                    low = low + 1
            indexC = indexC + 1
        return result
		
		
# 方法四:双指针。与方法三不同之处在于:程序自动地跳过重复元素(节省了很多时间)。
# 时间复杂度:O(n^2)
class Solution:
    def threeSum(self, nums: List[int]) -> List[List[int]]:
        result = []
        nums.sort()
        l = len(nums)
        for i in range(l):
            if i > 0 and nums[i] == nums[i-1]:   # 这步意义在于:跳过重复的C位元素。
                continue
            low, high = i+1, l-1
            while(low < high):
                tmp = nums[i] + nums[low] + nums[high]
                if tmp == 0:
                    result.append([nums[i], nums[low], nums[high]])
                    while(low < high and nums[low] == nums[low+1]):  # 跳过重复的low位元素
                        low = low + 1
                    while(low < high and nums[high] == nums[high-1]):  # 跳过重复的high位元素
                        high = high - 1
                    low = low + 1
                    high = high - 1
                elif tmp > 0:
                    high = high - 1
                else:
                    low = low + 1
        return result

知识点

1. continue 和 break 的区别

continue 跳过之后的代码,进入下次循环。即跳出本次循环。(可用于跳过重复元素,例如本例。)

break 跳出之后的所有循环。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Satisfying

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值