zoukankan      html  css  js  c++  java
  • 4Sum

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

    Note:

    • Elements in a quadruplet (a,b,c,d) must be in non-descending order. (ie, abcd)
    • The solution set must not contain duplicate quadruplets.
        For example, given array S = {1 0 -1 0 -2 2}, and target = 0.
    
        A solution set is:
        (-1,  0, 0, 1)
        (-2, -1, 1, 2)
        (-2,  0, 0, 2)
    
    分析:
     要从数列中找到4个数其和为给定值的所有组合,与3Sum一样要求输出结果升序和去重。
    一个简单直接的想法就是在3Sum解法上再嵌套一层,O(n^3)的时间复杂度,代码是丑陋而且难读的,估计时间上也过不了。
     
    重新思考一下解决方案,这个问题是可以化简为O(n^2)的。首先是做一个O(n^2)的计算,将这个数列里面每两个元素的和及其位置放到dict里面记录下来。然后我们的计算就变成
    x +y= target
    对dict里面的每个值做一次2Sum求值过程(不会超过O(n^2)),问题即可求解。
    具体实现过程,有一行代码比较复杂,要解释一下,
    map(values.add, [tuple(sorted((num[v1], num[v2], num[v3], num[v4]))) 
                        for v1, v2 in table[b] for v3, v4 in table[a] if len(set((v1, v2, v3, v4))) == 4])
    这行代码主要做了4件事情:

      1. 对两个二元组做笛卡尔积,生成4元组列表。如下的代码是做笛卡尔积比较简洁的方式

    python -c "print [(x, y) for x in [1,2,3] for y in [4,5]]"

      2. 对4元组去重,保证4元组的索引没有重复。列表去重的简单方式是做set然后看是否其长度和之前一样

    len(set((v1, v2, v3, v4))) == 4

      3. 对4元组进行排序,因为sorted生成的是list,还要转成tuple才能作为dict的key存储

      4. 将4元组加入set结构中,对每个元素应用map函数,调用set.add方法

    完整代码如下,

    class Solution:
    
        # @return a list of lists of length 4, [[val1,val2,val3,val4]]
        def fourSum(self, num, target):
            table = {}
            for i, a in enumerate(num):
                for j, b in enumerate(num[i + 1:], i + 1):
                    table.setdefault(a + b, []).append((i, j))
    
            values = set()
            for a in table:
                b = target - a
                if b in table:
                    map(values.add, [tuple(sorted((num[v1], num[v2], num[v3], num[v4]))) 
                        for v1, v2 in table[b] for v3, v4 in table[a] if len(set((v1, v2, v3, v4))) == 4])
            return map(list, values)
    
    if __name__ == '__main__':
        s = Solution()
        assert s.fourSum([1, 0, -1, 0, -2, 2], 0) == [[-1, 0, 0, 1], [-2, -1, 1, 2], [-2, 0, 0, 2]]
        print 'PASS'

    小结:

    找到合适的方法这个问题很容易解决。但是对于空间的要求比较高,如果数列很长,无法全部放入内存,应该如何做MapReduce?

  • 相关阅读:
    Memcached 内存分配机制介绍
    PHP与Memcached服务器交互的分布式实现源码分析
    yii 操作cookie
    Python urllib2递归抓取某个网站下图片
    mysql 知识 show status
    要读的书培根说:历史使人明智,诗词使人巧慧,算学使人精密,哲理使人深刻,伦理学人庄重,逻辑修辞使人善辩。
    思考的技术懒于求知的人没有生存空间
    相约星期二记录
    谁是最重要的人
    Netstat命令详解
  • 原文地址:https://www.cnblogs.com/openqt/p/4039225.html
Copyright © 2011-2022 走看看