zoukankan      html  css  js  c++  java
  • 3Sum

    Given an array S of n integers, are there elements a, b, c in S such that a + b + c = 0? Find all unique triplets in the array which gives the sum of zero.

    Note:

    • Elements in a triplet (a,b,c) must be in non-descending order. (ie, abc)
    • The solution set must not contain duplicate triplets.
        For example, given array S = {-1 0 1 2 -1 -4},
    
        A solution set is:
        (-1, 0, 1)
        (-1, -1, 2)
    
     

    分析:

    这个问题是要从数列里面找到所有和是0的3个数。

    对程序输出有两个限制,一是输出的三元组要按升序排列,二是输出的数列要去重,这在编码中会无法避免的导致检查和去重的代码实现。

    用map来实现过滤的话,会很容易导致超时,但是在实际应用中,还是觉得用map自动处理比较好理解,而且代码稳定易读。

    我写了一个函数,用来清楚表明3 Sum与2 Sum的区别。在这个twoSum里面实现了另外一种Two Sum的解法,略有差别是因为本题不需要返回索引,只要得到正确的数就可以了,所以省略了记录索引的步骤。

    class Solution:
    
        # @return a list of lists of length 3, [[val1,val2,val3]]
        def threeSum(self, num):
            values = []
    
            num.sort()
            for i, c in enumerate(num[:-2]):
                if c > 0:
                    break
                if i == 0 or num[i] > num[i - 1]:
                    values.extend(self.twoSum(num, c, i + 1))
            return values
    
        def twoSum(self, num, c, start):
            '''Another way for two sum problem'''
            c = -c
            values = []
            end = len(num) - 1
            while start < end:
                if num[start] + num[end] == c:
                    values.append([-c, num[start], num[end]])
                    start += 1
                    end -= 1
    
                    while start < end and num[start] == num[start - 1]:
                        start += 1
                    while start < end and num[end] == num[end + 1]:
                        end -= 1
                elif num[start] + num[end] < c:
                    start += 1
                else:
                    end -= 1
            return values
    
    if __name__ == '__main__':
        s = Solution()
        assert s.threeSum([-1, 0, 1, 2, -1, -4]) == [[-1, -1, 2], [-1, 0, 1]]
        assert s.threeSum([0, 0, 0]) == [[0, 0, 0]]
        assert s.threeSum([-2, 0, 1, 1, 2]) == [[-2, 0, 2], [-2, 1, 1]]
        assert s.threeSum([1, -1, -1, 0]) == [[-1, 0, 1]]
        print 'PASS'

    小结:

    这个问题与TwoSum结合起来思考的话并不难,但是如果考虑4个数值的衍生情况,是否是O(n^3)的复杂度?

    我附带贴上一个更为简洁的代码,但是无法过LeetCode的Online Judge,原因是为了代码的易读可靠超时了。LeetCode不支持set这个数据结构,否则

    values = set()

    更为简洁,避免了要给dict的value赋上一个值。

    def threeSum2(self, num):
            '''This solution much clear but time out'''
            values = {}
            table = dict(zip(num, range(len(num))))
            for i, c in enumerate(num[:-2]):
                for j, b in enumerate(num[i + 1:], i + 1):
                    a = -c - b
                    if a in table and table[a] not in (i, j):
                        values[tuple(sorted((a, b, c)))] = 1
    
            return map(list, values.keys())
  • 相关阅读:
    [055] SSL 3.0曝出Poodle漏洞的解决方式-----开发人员篇
    java中接口的定义与实现
    很好的理解遗传算法的样例
    Memory Architecture-SGA-Database Buffer Cache
    ActionScript3游戏中的图像编程(连载十七)
    MacOS的g++使用clang,默认不支持C++11多线程: no matching constructor for initialization of 'std::thread'
    bash代码
    delete
    nautilus-open-terminal右键随处打开终端
    删除系统多余内核
  • 原文地址:https://www.cnblogs.com/openqt/p/4038762.html
Copyright © 2011-2022 走看看