如何优化此代码以运行更大的值? [复制]

Posted

技术标签:

【中文标题】如何优化此代码以运行更大的值? [复制]【英文标题】:How do i optimize this code to run for larger values? [duplicate] 【发布时间】:2022-01-16 03:57:10 【问题描述】:

我正在编写一个 python 函数,该函数将 3 到 200 之间的整数值作为输入,使用等于该数字的唯一非零数字计算总和的数量并打印输出。 例如;以 3 作为输入 1 将被打印,因为只有 1 + 2 将给出 3,以 6 作为输入 3 将被打印,因为 1+2+3、1+5 和 2+4 等于 6。 我的代码仅适用于小于 30 的数字,之后它开始变慢。如何优化我的代码以高效运行 3 到 200 之间的所有输入。

from itertools import combinations

def solution(n):
    count = 0
    
    max_terms = 0
    num = 0
    for i in range(1,n):
        if num + i <= n:
            max_terms += 1
            num = num + i

    for terms in range(2,max_terms + 1):
        for sample in list(combinations(list(range(1,n)),terms)):
            if sum(sample) == n:
                count += 1

    print(count)

【问题讨论】:

首先,不要生成所有数字组合,然后过滤它们:只生成有效的组合。对于更大的数字,这变成了一个数学问题:不要生成组合,只需计算可以有多少组合。 这些只是分区,对吧? ***.com/questions/10035752/… 您的意思是“唯一的正数数”? “非零”数字将允许负数,这将允许对任何目标值进行无限数量的总和。 【参考方案1】:

生成所有组合确实不是很有效,因为大多数组合不会加起来n

相反,您可以使用递归函数,该函数可以在删除一个分区(即总和的一项)后调用,并且将解决剩余数量的问题,给出额外的指示,即未来的分区应该更大比刚刚拍的那个。

为了进一步提高效率,可以使用memoization(动态规划)来避免多次求解同一个子问题。

下面是代码:

def solution(n, least=1, memo=):
    if n < least:
        return 0
    key = (n, least)
    if key in memo:  # Use memoization
        return memo[key]
    # Counting the case where n is not partitioned
    #    (But do not count it when it is the original number itself)
    count = int(least > 1)
    # Counting the cases where n is partitioned
    for i in range(least, (n + 1) // 2):
        count += solution(n - i, i + 1)
    memo[key] = count
    return count

用这些参数测试了代码。 cmets 列出了计算的总和:

print(solution(1)) # none
print(solution(2)) # none
print(solution(3)) # 1+2
print(solution(4)) # 1+3
print(solution(5)) # 1+4, 2+3
print(solution(6)) # 1+2+3, 1+5, 2+4
print(solution(7)) # 1+2+4, 1+6, 2+5, 3+4
print(solution(8)) # 1+2+5, 1+3+4, 1+7, 2+6, 3+5
print(solution(9)) # 1+2+6, 1+3+5, 2+3+4, 1+8, 2+7, 3+6, 4+5
print(solution(10)) # 1+2+3+4, 1+2+7, 1+3+6, 1+4+5, 2+3+5, 1+9, 2+8, 3+7, 4+6

【讨论】:

【参考方案2】:

你的问题不够清楚。所以,我在做一些假设......

所以,你想要的是输入一个数字。说 4,然后找出两个不同数字加起来的总组合。如果这是您想要的,那么答案很简单。

对于 4,我们将其视为“n”。 'n' 的组合为 1+3,2+2。

对于 n 为 6,组合为 - 1+5,2+4,3+3。

您可能已经发现了一种模式。 (4 和 6 有一半的组合)同样,对于奇数,它们的组合是之前偶数的一半。即 - 5 有 (4/2)=2 组合。即 1+4,2+3 所以...

得到组合数的公式是 -

    (n)/2 - 如果您想包含相同的数字组合,例如 2+2 对应 4,但排除 0 组合。即 0+4 对应 4

    (n+1)/2 - 如果您想排除 0 的组合,即 4 的 0+4 或具有相同数字的组合,即 4 的 2+2,则此方法有效。

    (n-1)/2 - 在这里,相同数量的组合被排除在外。即 2+2 不会被算作 n 为 4 的组合。此外,0 组合即 4 的 0+4 被排除在外。

n 是主要数字。在这些示例中,它是“4”。这仅在 n 是整数并且计算后的这些值存储为整数时才有效。 3个数字组合完全不同。我敢肯定也有一个公式。

【讨论】:

您需要有一个公式来生成 3 个术语、4 个术语、5 个术语、6 个术语等。真的没有尽头。因此,只有特定数量的分区的公式无济于事。需要一个更通用的解决方案来解决所有问题。

以上是关于如何优化此代码以运行更大的值? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

CSV:如何在列表中找到下一个更大的值(python)?

MySQL:如何获得视图的模块化,但优化更长的代码?

如何过滤更大的文本字体?

如何优化此代码以摆脱“超出时间限制”问题?

对RDD进行Spark重复数据删除以获得更大的RDD

带有连接和子查询的 mysql 查询优化