【问题标题】:Find the subset of a set of integers that has the maximum product找到具有最大乘积的整数集的子集
【发布时间】:2016-10-04 05:01:53
【问题描述】:

令 A 为非空整数集。编写一个函数 find,它输出 A 的具有最大乘积的非空子集。例如,find([-1, -2, -3, 0, 2]) = 12 = (-2)*(-3)*2

这是我的想法:将列表分为正整数列表和负整数列表:

  1. 如果我们有偶数个负整数,将两个列表中的所有内容相乘,我们就有了答案。
  2. 如果我们有奇数个负整数,找出最大的一个并将其从列表中删除。然后将两个列表中的所有内容相乘。
  3. 如果列表只有一个元素,则返回该元素。

这是我的 Python 代码:

def find(xs):
    neg_int = []
    pos_int = []
    if len(xs) == 1:
        return str(xs[0])
    for i in xs:
        if i < 0:
            neg_int.append(i)
        elif i > 0:
            pos_int.append(i)
    if len(neg_int) == 1 and len(pos_int) == 0 and 0 in xs:
        return str(0)
    if len(neg_int) == len(pos_int) == 0:
        return str(0)
    max = 1
    if len(pos_int) > 0:
        for x in pos_int:
            max=x*max
    if len(neg_int) % 2 == 1:
        max_neg = neg_int[0]
        for j in neg_int:
            if j > max_neg:
                max_neg = j
        neg_int.remove(max_neg)
    for k in neg_int:
        max = k*max
    return str(max)

我错过了什么吗?附言这是来自 Google 的 foobar 挑战的问题,我显然错过了一个案例,但我不知道是哪个案例。

现在这是实际问题:

【问题讨论】:

  • 我的意思是数字上最大的负数,如 -1 > -3
  • 做 max_neg = abs(neg_int[0]).. 并根据绝对值做比较
  • 集合是否需要是最小大小的集合?例如[2, 3, 1, 1] 产生与 [2, 3] 相同的产品。挑战是否说明了您应该如何解决这种差异?
  • 不,它没有。我应该说从技术上讲它不是一个集合,因为可以存在重复的值。
  • @Lewis:认为我发现你的代码有错误:假设输入是:[-1],你的代码返回0作为答案。在某些极端情况下,你return 0 return str(0)

标签: python algorithm


【解决方案1】:
from functools import reduce
from operator import mul

def find(array):
    negative = []
    positive = []
    zero = None
    removed = None

    def string_product(iterable):
        return str(reduce(mul, iterable, 1))

    for number in array:
        if number < 0:
            negative.append(number)
        elif number > 0:
            positive.append(number)
        else:
            zero = str(number)

    if negative:
        if len(negative) % 2 == 0:
            return string_product(negative + positive)

        removed = max(negative)

        negative.remove(removed)

        if negative:
            return string_product(negative + positive)

    if positive:
        return string_product(positive)

    return zero or str(removed)

【讨论】:

    【解决方案2】:

    您可以使用reduce(在Py3 中的functools 中)简化这个问题

    import functools as ft
    from operator import mul
    
    def find(ns):
        if len(ns) == 1 or len(ns) == 2 and 0 in ns:
            return str(max(ns))
        pos = filter(lambda x: x > 0, ns)
        negs = sorted(filter(lambda x: x < 0, ns))
        return str(ft.reduce(mul, negs[:-1 if len(negs)%2 else None], 1) * ft.reduce(mul, pos, 1))
    
    >>> find([-1, -2, -3, 0, 2])
    '12'
    >>> find([-3, 0])
    '0'
    >>> find([-1])
    '-1'
    >>> find([])
    '1'
    

    【讨论】:

    • 这个解决方案似乎在输入 [-1] 上崩溃并且不返回字符串。
    • 好吧,它没有涵盖所有的特殊情况。增加了一个守卫。
    【解决方案3】:

    这是一个循环的解决方案:

    def max_product(A):
        """Calculate maximal product of elements of A"""
        product = 1
        greatest_negative = float("-inf") # greatest negative multiplicand so far
    
        for x in A:
            product = max(product, product*x, key=abs)
            if x <= -1:
                greatest_negative = max(x, greatest_negative)
    
        return max(product, product // greatest_negative)
    
    assert max_product([2,3]) == 6
    assert max_product([-2,-3]) == 6
    assert max_product([-1, -2, -3, 0, 2]) == 12
    assert max_product([]) == 1
    assert max_product([-5]) == 1
    

    额外的功劳:如果放宽整数约束会怎样?在循环过程中您需要收集哪些额外信息?

    【讨论】:

      【解决方案4】:

      这是另一个不需要库的解决方案:

      def find(l):
          if len(l) <= 2 and 0 in l: # This is the missing case, try [-3,0], it should return 0
              return max(l)
          l = [e for e in l if e != 0] # remove 0s    
          r = 1
          for e in l: # multiply all
              r *= e 
          if r < 0: # if the result is negative, remove biggest negative number and retry
              l.remove(max([e for e in l if e < 0]))
              r = find(l)
          return r
      
      print(find([-1, -2, -3, 0, 2])) # 12
      print(find([-3, 0])) # 0
      

      编辑:

      我想我找到了缺失的情况,即列表中只有两个元素,最高为 0。

      【讨论】:

      • 这是一个非常好的解决方案。但它失败了与我的代码相同的测试用例。 (遗憾的是我不知道是哪种情况)
      • @Lewis 也是我的想法,但我真的看不出是什么情况。我会继续寻找,这个问题很有趣:)
      • 实际上您的解决方案也失败了另一种情况:find([0,-1)] 打印 1 而不是 0。
      • 我刚刚更新了问题。请看描述中的图片。 :)
      • 当你给这个代码一个负数时,find([-3])它返回1。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-08-24
      • 1970-01-01
      • 2020-08-30
      • 1970-01-01
      • 2023-01-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多