【问题标题】:Target sum of an infinite stream of numbers in pythonpython中无限数字流的目标总和
【发布时间】:2020-07-09 21:40:14
【问题描述】:

我试图找到一个目标总和可以从 Python 中的无限数字流中找到。数字是正数(数字> 0),唯一且数字是不确定的。我相信答案是使用动态编程或堆,但不能完全弄清楚逻辑。

关于可能的数据结构或逻辑流程的任何帮助。

非常感谢。

例如

    nums = [ 99,85,1,3,6,72,7,9,22,....]
    targetSum = 27

output: True
Explanation: 1+6+22 = 27(targetSum)

【问题讨论】:

  • 你确定你的意思是无限吗?我认为您的意思是数字列表。
  • 你好,是的,从连续数字流的意义上说是无限的。我们不知道流的长度。
  • 您希望我们为您实现一个算法,该算法从有限列表中确定一组成员,添加的结果是 targetSum?到目前为止你尝试了什么?如果 nums 是有限的(带有 n 元素),请尝试以下操作: - 尝试所有 n 可能性 从列表中挑选一个条目,看看它是否是 targetSum - 从列表中挑选两个条目,看看是否它的总和是 targetSum 如果没有找到结果,请尝试 3 个条目,...直到您尝试了 n 个条目。看看模块itertoolscombinations 功能,对你有帮助
  • 你的意思是indefinite(未定义/长度未知,它未定义)或infinite 该列表将不适合内存,因为到目前为止总是有另一个成员您没有访问在里面)
  • 嗨@gelonida,感谢您提供可能的解决方案。我的意思是无限的,其中列表不适合内存。如果可以就如何解决这个问题提出一个逻辑建议,那就太好了。

标签: python algorithm stream sum logic


【解决方案1】:

您可以使用集合来跟踪到目前为止迭代中给定数字的所有可能总和。对于每次迭代,将当前数字添加到集合中的每个现有总和以添加到集合中,并将当前数字本身添加到集合中。当目标总和确实在集合中时返回True

def has_sum(nums, targetSum):
    sums = set()
    for i in nums:
        sums.update([s + i for s in sums if s + i <= targetSum])
        if i <= targetSum:
            sums.add(i)
        if targetSum in sums:
            return True
    return False

这样:

has_sum([99, 85, 1, 3, 6, 72, 7, 9, 22], 29)

返回 True(因为 1 + 6 + 22 = 29),并且:

has_sum([99, 85, 1, 3, 6, 72, 7, 9, 22], 27)

返回False(因为您问题中的预期输出不正确)。

【讨论】:

  • 感谢您的解决方案。这是一个不错的、快速的蛮力解决方案,但如果流中有数千个数字怎么办。在这种情况下我们如何管理内存?
  • 那么您将用时间来节省内存,因为如果您不将以前的总和保存在内存中,您将花费时间重新访问所有以前的数字以重新计算每个新的所有以前的总和号码。
  • 谢谢@blhsing。是的,在这种情况下我们必须进行权衡,但想知道是否有办法只存储选定的先前总和(不确定是否可以制定此标准)
  • 注意。您实际上只需要存储低于或等于目标总和的总和。此外,如果您将其设为字典,说明最后添加的数字是为了得到这个总和,那么您可以向后工作并生成实际加起来的子集。
  • @btilly 请注意,在我写完这个答案之后,OP 添加了这个约束。
【解决方案2】:

@帕维斯,

我能想到的一个想法是使用紧密图。您可以执行以下操作:

  1. 将小于和的每个数字元素作为节点添加到图中
  2. 每个新节点都连接到图中已经存在的每个其他节点
  3. 添加到图形后,使用从最低元素开始的广度优先搜索计算总和

我认为这个过程很慢

【讨论】:

    【解决方案3】:

    您可以递归地尝试在给定序列中使用或不使用第一个数字来满足目标总和,直到给定序列中没有更多数字,或者直到给定目标总和不再是正数(因为您在评论所有给定的数字都是正数):

    def has_sum(nums, targetSum):
        if not nums or targetSum <= 0:
            return False
        first, *rest = nums
        return first == targetSum or has_sum(rest, targetSum - first) or has_sum(rest, targetSum)
    

    这样:

    has_sum([99, 85, 1, 3, 6, 72, 7, 9, 22], 29)
    

    返回 True(因为 1 + 6 + 22 = 29),并且:

    has_sum([99, 85, 1, 3, 6, 72, 7, 9, 22], 27)
    

    返回False(因为您问题中的预期输出不正确)。

    编辑:为避免在每次调用中将输入序列减去第一项复制到 rest 对性能的影响,可以使用索引来改进上面的代码:

    def has_sum(nums, targetSum, index=0):
        if index == len(nums) or targetSum <= 0:
            return False
        num = nums[index]
        return num == targetSum or has_sum(nums, targetSum - num, index + 1) or has_sum(nums, targetSum, index + 1)
    

    【讨论】:

      猜你喜欢
      • 2020-08-30
      • 2022-12-18
      • 1970-01-01
      • 1970-01-01
      • 2021-05-18
      • 2021-08-28
      • 2019-06-27
      • 2019-03-16
      • 1970-01-01
      相关资源
      最近更新 更多