【问题标题】:Optimization in a time based algorithm基于时间的算法中的优化
【发布时间】:2015-06-21 08:32:43
【问题描述】:

我正在为这个问题写一个算法,算法很简单,我已经写了代码但是我看不到任何可能的优化:

我有一个装有 100 块石头的桶和 5 个孩子用它来装饰他们的沙堡。 每个孩子每隔一定时间重复捡石头,每个孩子都是独立的,更多的孩子可以同时捡石头,总共有5个孩子:

  • 埃里克每 5 分钟捡起一块石头
  • 马克每 10 分钟捡起一块石头
  • 劳拉每 7 分钟捡起一块石头
  • 艾玛每 3 分钟捡起一块石头
  • 弗兰克每 3 分钟捡起一块石头

清空桶到底需要多少分钟?

更清楚一点:10 分钟后,Erick 有两颗石子(第 5 分钟和第 10 分钟),而 Emma 有 3 颗石子(第 3、6 和 9 分钟)。

所以 10 分钟后孩子们总共有 2 + 1 + 1 + 3 + 3 = 10 块石头,桶里有 90 块石头

这是我的代码(Python 3):

children_rate = [3, 3, 5, 7, 10]
bucket = 100

minutes = 0

while True:
    minutes += 1
    for child in children_rate:
        if minutes % child == 0:
            bucket -= 1
            if bucket == 0:
                print('bucket empty in',minutes,'minutes')
                exit()

此代码有效,在这种情况下所需的分钟数为 91,但我不能使用此代码处理一个有 100 万块石头和 500 个孩子的桶。

我能看到的唯一优化是将 mod 操作转换为 sum/add 操作,因为除法/乘法更昂贵。我可以使用 numpy 数组等等,但没有什么可以真正加快这个过程。

我试图将这个问题改编为我的算法教科书中描述的一些典型已知问题,但没有运气。

【问题讨论】:

    标签: python algorithm optimization time-complexity


    【解决方案1】:

    您可以翻转算法,以便在给定的分钟数内计算所有孩子使用了多少石头。

    def compute_stones(minutes)
        stones = 0
        for child in children_rate:
            stones += minutes // child  # integer division
        return stones
    

    然后你可以做一个二进制切分来找到石头 = 100 的分钟数

    【讨论】:

    • 既然问题被标记为python-3.x,那么楼层划分不应该是//吗?
    【解决方案2】:

    您可以做的一件事是对答案进行二分搜索。

    假设答案是X 分钟。 然后你就知道每个孩子在那段时间会拿多少石头。 如果取出的石头总数少于预期,X 需要更高。 否则,在下半部分搜索。

    在代码中:

    children_rate = [3, 3, 5, 7, 10]
    bucket = 100
    
    lo, hi = 0, bucket * max (children_rate)
    while lo < hi:
        me = (lo + hi) // 2
        if sum (me // i for i in children_rate) < bucket:
            lo = me + 1
        else:
            hi = me
    
    print (lo)
    

    【讨论】:

      【解决方案3】:

      每个孩子在某个时期捡石头,所有孩子一起以某种图案捡石头,该图案也有一个时期。此模式的周期是每个孩子的周期Least common multiple。它可以通过多种方式计算,但在这种情况下,让我们使用每个周期的因式分解。

      3  =   3
      5  =     5
      7  =       7
      10 = 2 * 5
      

      所以常见的句号是210 = 2 * 3 * 5 * 7。这一次,埃里克挑了 42 颗石头,马克挑了 21 颗,劳拉挑了 30 颗,艾玛和弗兰克各挑了 70 颗。每 210 分钟有 233 颗石头。如果你在一个桶里有 100 万颗石头,他们会在 901110 分钟内挑选出 999803 颗石头,而你将为剩下的 197 颗石头运行你的原始代码。很简单,不是吗?

      【讨论】:

      • 即使对于少数孩子,周期也可能非常大(与所有孩子周期的乘积一样大,例如,如果它们是不同的素整数)。所以这种方法是不切实际的,除非我们知道孩子的周期都是非常小的整数,或者保证有一个小的 LCM。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-04-17
      • 2021-12-20
      • 1970-01-01
      • 2023-03-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多