zoukankan      html  css  js  c++  java
  • LeetCode Prob.15 3Sum

    先挖坑,补上几个大佬的代码

    第一个代码,用的是双指针法,思想靠近于2Sum。

    首先,对数组进行排序。

    然后,对于以下三种情况,可以直接判断无解:

    • 长度为0(其实可以说长度小于3)
    • 最小数字大于0,即数组全大于0
    • 最大数字小于0,即数组全小于0

    接着我们对数组进行遍历。当我们选定了当前点,例如,nums[pt],之后,就有了一个2Sum的目标:0 - nums[pt]

    需要注意的是,由于遍历相当于将搜索空间从左边缩小,因此 10 行有个相应的判断条件。

    现在我们要做的就是在left =  pt + 1 到 right = len(nums) - 1 之间,寻找2Sum的结果为 0 - nums[pt] 的二元组。

    而且,这种寻找方式可以确保,pt, left, right 是单调上升的。

    此外,在寻找到了结果之后,还并不能就此结束,因为在寻找到的 left 和 right 的内部还有可能出现满足的二元组。这也是 20 行到 23 行的意义。

    并且,我们的寻找,已经找出了 pt + 1 到 len(nums) - 1 之间所有对应 0 - nums[pt]的二元组,所以我们可以在 11 行跳过同等的数字。

    其它基本上就没有什么好说的了,如果2Sum的原理不懂可以去看看题目,很简单的。

     1 class Solution:
     2     def threeSum(self, nums: List[int]) -> List[List[int]]:
     3         nums.sort()
     4         #print (nums)
     5         #pre judging
     6         if len(nums) == 0 or nums[0] > 0 or nums[-1] < 0: return []
     7         ans = []
     8         pt = 0
     9         while pt < len(nums) - 2: #there must be 2 numbers ahead 
    10             if nums[pt] > 0: break
    11             if pt > 0 and nums[pt] == nums[pt - 1]:
    12                 pt += 1
    13                 continue
    14             left = pt + 1
    15             right = len(nums) - 1
    16             #print (nums[pt], nums[left], nums[right])
    17             while left < right:
    18                 if nums[pt] + nums[left] + nums[right] == 0:
    19                     ans.append([nums[pt], nums[left], nums[right]])
    20                     while left < right and nums[left] == nums[left + 1]: left += 1
    21                     while left < right and nums[right] == nums[right - 1]: right -= 1
    22                     left += 1
    23                     right -= 1
    24                 elif nums[pt] + nums[left] + nums[right] > 0:
    25                     right -= 1
    26                 else:
    27                     left += 1
    28             pt += 1
    29         return ans 
    30             
    31             
     1 class Solution:
     2     def threeSum(self, nums):
     3         """
     4         :type nums: List[int]
     5         :rtype: List[List[int]]
     6         """
     7         d = {}
     8         for val in nums:
     9             d[val] = d.get(val, 0) + 1
    10         
    11         pos = [x for x in d if x > 0]
    12         neg = [x for x in d if x < 0]
    13         
    14         res = []
    15         if d.get(0, 0) > 2:
    16             res.append([0, 0, 0])
    17             
    18         for x in pos:
    19             for y in neg:
    20                 s = -(x + y)
    21                 if s in d:
    22                     if s == x and d[x] > 1:
    23                         res.append([x, x, y])
    24                     elif s == y and d[y] > 1:
    25                         res.append([x, y, y])
    26                     elif y < s < x:
    27                         res.append([x, y, s])
    28         return res
     1 class Solution:
     2     def threeSum(self, nums: 'List[int]') -> 'List[List[int]]':
     3         from bisect import bisect_left, bisect_right
     4        
     5         target = 0
     6         
     7         result = []
     8         length = len(nums)
     9         
    10         if length < 3:
    11             return result
    12         
    13         count ={}
    14         # map the counts
    15         for n in nums:
    16             if n in count:
    17                 count[n] += 1
    18             else:
    19                 count[n] = 1
    20             
    21         keys = list(count.keys())
    22         keys.sort()
    23       
    24         t3 = target // 3
    25         if t3 in keys and count[t3] >= 3:
    26             result.append([t3, t3, t3])
    27 
    28         begin = bisect_left(keys, target - keys[-1] * 2)
    29         end = bisect_left(keys, target * 3)
    30 
    31         for i in range(begin, end):
    32             a = keys[i]
    33             if count[a] >= 2 and target - 2 * a in keys:
    34                 result.append([a, a, target - 2 * a])
    35 
    36             max_b = (target - a) // 2  # target-a is remaining
    37             min_b = target - a - keys[-1]  # target-a is remaining and c can max be keys[-1]
    38             b_begin = max(i + 1, bisect_left(keys, min_b))
    39             b_end = bisect_right(keys, max_b)
    40 
    41             for j in range(b_begin, b_end):
    42                 b = keys[j]
    43                 c = target - a - b
    44                 if c in count and b <= c:
    45                     if b < c or count[b] >= 2:
    46                         result.append([a, b, c])
    47         return result
  • 相关阅读:
    Python/WSGI 应用快速入门--转
    汇编题目:数字转字符,并在窗口上显示出来
    汇编题目:在窗口上显示Welcome to masm!
    VBA中的函数Timer用法
    用VBA计算两个日期之间的工作日(去掉周末两天)
    VBA记录当前系统时间并精确到毫秒
    上海房产税免征--积分或居住证
    学习汇编语言
    “Hello World”—— 第一个汇编程序
    汇编程序设计上机步骤
  • 原文地址:https://www.cnblogs.com/KakagouLT/p/10440655.html
Copyright © 2011-2022 走看看