【问题标题】:Get the indices of a list whose value add up to the given number获取其值加起来等于给定数字的列表的索引
【发布时间】:2016-04-14 16:02:58
【问题描述】:

我有一个值列表,我输入了一个数字。该函数必须返回列表中其值加起来等于数字的索引。问题是列表包含重复的数字,并且返回的索引不应该相同。这是我所拥有的,但解决方案看起来并不干净。有没有更好的办法?

finalList = []
def getIndices(number):
  values = [10,20,20,50,100,200,200,500,1000,2000,2000,5000]
  for i in range(len(values)):
    if values[i] == number:
      if i not in finalList:
        finalList.append(i)
      else:
        finalList.append(i-1)
      return values
    elif values[i] < number:
      continue
    else:
      number = number - values[i-1]
      if i-1 not in finalList:
        finalList.append(i-1)
      else:
        finalList.append(i-2)
      if number <= 0:
        break
      return getIndices(number)


result = getIndices(450)
print(result)

输出

[6, 5, 3]

如果我在添加之前没有检查列表,那么我会得到[6, 6, 3],这不是我想要的。

【问题讨论】:

  • 首先将列表转换为set 以消除欺骗?
  • @BAH 不会改变索引号吗?
  • 可以有多个答案。你希望他们全部归还吗?例如,如果数字是 50,则 [0,1,2] 和 [3] 都是有效答案。
  • 列表排序了吗?如果它是排序的,你至少可以忽略所有值 >= 到数字,你可以快速找到使用二分法的索引。
  • @KR29 但 10+20+20 也是 50 所以我不明白

标签: python python-3.x


【解决方案1】:

如果对值列表进行了排序,则以下代码将执行您想要的操作。这里的诀窍是以相反的顺序遍历列表。

但请注意函数中的编辑和最后一次测试!

编辑:这个问题被称为子集和问题(参见Wikipedia)并且是NP完全的。应该马上认出来,我的错。这基本上意味着没有简单有效的解决方案。最简单的解决方案是尝试所有可能的组合,但如果您的值列表很大,则完成所需的时间太长。

def getIndices(number, values):
    '''Return a tuple (n, l) where l is a list of indices in 'values' and the
    following condition holds: n + sum(values[i] for i in l) == number.

    values -- sorted list of numbers
    number -- sum to search for

    >>> values=[10,20,20,50,100,200,200,500,1000,2000,2000,5000]
    >>> getIndices(18000, values)
    (6900, [11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0])
    >>> getIndices(450, values)
    (0, [6, 5, 3])
    >>> getIndices(15, values)
    (5, [0])
    >>> getIndices(10, values)
    (0, [0])
    >>> getIndices(5, values)
    (5, [])
    >>> getIndices(0, values)
    (0, [])

    This simplicist algorithm does not always find a solution with 'n' == 0,
    even if one exists. The following test fails, it returns (10, [2])
    instead.

    >>> getIndices(40, [20, 20, 30])
    (0, [0, 1])

    '''
    n = number
    l = []

    for i in range(len(values) - 1, -1, -1):
        if values[i] <= n:
            l.append(i)
            n -= values[i]

    assert(n + sum(values[i] for i in l) == number)
    return n, l


if __name__ == '__main__':
    import doctest
    doctest.testmod()

【讨论】:

  • 你不妨“翻转”列表
  • 当然,如果你可以保持列表向后排序,你可以向前走。
  • 另外,这个用例在 n = 0 时失败(甚至在 n = 10 时失败)
  • @Markus 谢谢你解决了这个问题。毕竟我不需要递归!
  • 我认为 finalList 应该在函数中定义。你也可以改用return finalList[::-1]
猜你喜欢
  • 2011-11-11
  • 1970-01-01
  • 1970-01-01
  • 2022-11-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多