LeetCode #15 3Sum

题目

3Sum


解题方法

a + b + c = 0的问题可以等价于a + b = 0 - c的问题,令target = 0 - c,套用#1 Two Sum的解题方法即可破题。

需要注意的是两道题的返回值有所不同,此题返回值是一个嵌套列表,由多个不重复的子列表组成,每个列表中三个数相加都是0。因此需要考虑列表去重问题,有两种办法:

  1. 在执行过程中跳过重复项;
  2. 先获取所有结果,再去掉其中重复项。

我采用的方法是将两种去重方法结合,在第一重循环中跳过重复项,然后执行常规的Two Sum解题,最后再利用python的集合set元素不重复的特性去重。

一般的list去重只需要用list(set(列表))即可,代码如下:

res = [1,2,3,4,5,1,2,3]
list(set(res))

嵌套列表去重需要用到tuple,代码如下:

temp_set = set(tuple(i) for i in old_list)
new_list = [list(t) for t in temp_set]

需要注意的是,这样写需要列表中每一个子列表都是按照一定顺序排列好的,例如[[1,2,3], [1,3,2], [2,3,1]]如果不排序为[[1,2,3], [1,2,3], [1,2,3]],将被set认定为不重复的元素项,与此题题意不符,因此需要在去重前先对每一个子列表进行排序:

for i, t in enumerate(old_list):
    t.sort()

代码

class Solution:
    def threeSum(self, nums: List[int]) -> List[List[int]]:
        res = []
        nums.sort()
        
        for i in range(len(nums)-2):
            if i and nums[i] == nums[i-1]:
                continue
            dic = {}
            target = 0 - nums[i]
            for j in range(i+1, len(nums)):
                if target - nums[j] in dic:
                    res.append([nums[i], nums[j], target-nums[j]])
                dic[nums[j]] = j
        
        temp = set(tuple(i) for i in res)
        ret = [list(t) for t in temp]
        
        return ret

改进版,利用set.add()方法在添加重复元素时不执行操作的特性,省去嵌套列表去重操作,节省运行时间。

class Solution:
    def threeSum(self, nums: List[int]) -> List[List[int]]:
        if len(nums) < 3:
            return []
        nums.sort()
        res = set()

        for i, v in enumerate(nums[:-2]):
            if i >= 1 and v == nums[i-1]:
                continue
            d = {}
            for x in nums[i+1:]:
                if x not in d:
                    d[-v-x] = 1
                else:
                    res.add((v, -v-x, x))

        return map(list, res)
posted @ 2020-09-21 09:45  老鼠司令  阅读(93)  评论(0)    收藏  举报