【leetcode解题历程与思考】15. 3Sum 【python】

最开始的思路,是希望尽量不要重复遍历,第一次的解法是:

   def threeSum(nums):
       """
       :type nums: List[int]
       :rtype: List[List[int]]
       """
       nums.sort()
       if nums[0] > 0:
           return []
       elif nums[len(nums)-1] < 0:
           return []
       else:
           result = list()
           head = 0
           tail = len(nums)-1
           ind = 0
       for i in range(head,tail+1):
           if nums[i]>=0:
               ind = i
               break
       while head <= ind <= tail:
           if nums[head]+nums[tail] > 0 or ind == tail:
               for i in range(ind, head, -1):
                   if nums[head]+nums[tail] + nums[i] == 0:
                       result.append([nums[head],nums[tail],nums[i]])
                       head = head + 1
                       break
                   elif nums[head]+nums[tail] + nums[i] < 0:
                       head = head + 1
                       break
               tail = tail - 1
           elif nums[head]+nums[tail] < 0:
               for i in range(ind, tail):
                   if nums[head]+nums[tail] + nums[i] == 0:
                       result.append([nums[head],nums[tail],nums[i]])
                       tail = tail - 1
                       break
                   elif nums[head]+nums[tail] + nums[i] > 0:
                       tail = tail - 1
                       break
               head = head + 1
           else:
               if nums[ind] == 0:
                   result.append([nums[head], 0, nums[tail]])
                   if nums[head] == num[tail]:
                       break
                   else:
                       head = head + 1
       return result

逻辑:县排序,前面特殊情况判断不解释,后面,当正数(tail)比负数(head)大时,从负数处找另一个解,即 for i in range(ind, head, -1): ind为中间数,从中间遍历可以尽早找到解(如果有的话),当二者相加小于等于0时,没有继续向前遍历的意义了,就终止,head向后挪一位,这个较大的正数(tail)与所有可能的两个负数遍历完之后,tail-1。正数比负数小时,同理。
但是这种方法始终存在覆盖不了的情况(一脸懵逼= =跪求指点,等我想出是哪里出问题再来更新)

放弃第一种解法之后,开始妥协遍历的重复率,第二种解法:

  class Solution:
      def threeSum(self,nums):
          """
          :type nums: List[int]
          :rtype: List[List[int]]
          """
          nums.sort()
          if len(nums) < 3:
              return []
          left = 0
          right = len(nums)-1
          result = []
          while nums[left] <= 0 and left < right:
              while nums[right] >= 0 and left < right:
                  if nums[right] + nums[left] > 0:
                      n = left + 1
                      while nums[n] < 0 and nums[right] + nums[left] + nums[n] <= 0:
                          if nums[right] + nums[left] + nums[n] == 0 and [nums[left], nums[n], nums[right]] not in result:
                              result.append([nums[left], nums[n], nums[right]])
                          n = n + 1
                  elif nums[right] + nums[left] < 0:
                      n = right - 1
                      while nums[n] > 0 and nums[right] + nums[left] + nums[n] >= 0:
                          if nums[right] + nums[left] + nums[n] == 0 and [nums[left], nums[n], nums[right]] not in result:
                              result.append([nums[left], nums[n], nums[right]])
                          n = n - 1
                  else:
                      n = left + 1
                      while nums[n] <= 0 and n < right:
                          if nums[n] == 0 and [nums[left], nums[n], nums[right]] not in result:
                              result.append([nums[left], nums[n], nums[right]])
                          n = n+1
                  right = right -1
              right = len(nums) - 1
              left = left + 1
          return result

逻辑:对每个负数(下标left),寻找一个正数right,和一个中间数(n),n的取值范围根据left和right的大小来决定。但此方法提交会超时(3层循环)

最终采用答案里的解法:

   class Solution:
       def threeSum(self,nums):
           result={}
           nums.sort()
           for i,num in enumerate(nums):
               left = i + 1
               right = len(nums) - 1
               while left < right:
                   s = nums[i] + nums[left] + nums[right]
                   if s < 0 :
                       left+=1
                   elif s > 0:
                       right-=1
                   else:
                       if (nums[i], nums[left], nums[right]) not in result:
                           result[(nums[i], nums[left], nums[right])] = 1
                       if nums[left] == nums[right]:
                           break
                       left+=1
                       right-=1
           return list(result.keys())

逻辑:对每个数向右找两位能相加为0的数,遍历整个数组。答案通过(只有两层循环)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值