【问题标题】:Determining the number of possible combinations of a number to get a specified result确定一个数字的可能组合的数量以获得指定的结果
【发布时间】:2014-05-06 21:02:07
【问题描述】:

我遇到了这个问题:

给定一个整数,仅使用 2,3,7 来确定可能的组合数,其总和将给出整数。

例如:

4 - 2  {(2,2)}
9 - 3  {(2, 7), (2, 2, 2, 3), (3, 3, 3)}

一种方法是遍历 3 个循环,然后确定总和是否可达到。代码如下:

for( i=0; i<=num/2; i++){
    for( j=0; j<=num/3; j++){
         for( k=0; k<=num/7; k++){
            if(i*2+j*3+k*7 == num) 
                 count++;
}

这里的 count 将有可能的集合数。但这是非常低效的并且需要 O(n3) 时间。我想知道是否有任何其他有效的方法来计算不同集合的数量。

【问题讨论】:

标签: algorithm combinations


【解决方案1】:

这可以在 O(n^2) 内解决。

避免最后一个循环。

for( i=0; i<=num/2; i++){
    for( j=0; j<=num/3; j++){
        k = num - i*2 - j*3;
        if(k%7==0)
                 count++;
    }
}

【讨论】:

  • 你认为你的第一个循环num/7会更好吗?
  • 是的!但这并不多:)
  • @PhamTrung 解释为什么你觉得 num/7 更好?如果给定的数字是 7 怎么办?
  • 我回答的代码的复杂度是 O(num^2/6)。如果在外循环中使用 7 和 3,复杂度可以降低到 O(num^2/21)。
  • @user1677597 因为 for 循环从 0 开始,所以即使数字是 7,它仍然可以,类似于 case num/2,对于从 0 到 num/7 的 for 循环和从 0 到 num/2 ,哪个更短?只是简单的数学
【解决方案2】:

这个问题的 dp 解决方案应该是线性的。 (Implemented here)

#include <stdio.h>
#define SZ 5
int memo[SZ+1+7];


int main(void) {
    int i = 0;
    memset(&memo[0], 0, sizeof memo);
    memo[0] = 1;

    for(i = 0; i <= SZ; ++i) memo[i+2] += memo[i];
    for(i = 0; i <= SZ; ++i) memo[i+3] += memo[i];
    for(i = 0; i <= SZ; ++i) memo[i+7] += memo[i];

    printf("%d\n", memo[SZ]);

    return 0;
}
  1. 我们从具有理想无限大小的一维 dp 数组 memo 开始 (在实践中动态分配)大小不会导致 索引 SZ + max_num 的边界。
  2. 用 1 初始化这个数组的元素 0,因为有 1 种方式 获取empty_sum。
  3. 如果我们可以通过x种方式获得一个数字k,那么还有x种方式 获取k+2k+3k+7。这是 3 个循环正在使用的内容。 (Number_of_ways[{2,3,7}+i] += number_of_ways[i])
  4. 所有循环完成后,memo[k : 0 - SZ] 包含 我们可以获得 k 的方法

给出 O(k * N) 的复杂度,这里 k 为 3 (2, 3, 7)。对于常数 k,这是线性的。

【讨论】:

  • 如果 n 为 5,您的公式返回 2,这是错误的,它应该只返回 1 (2 + 3)
  • 它认为2+33+2 不同
  • 我认为他要求的是组合,而不是排列,他的例子很清楚这一点
  • 作者指定9应该返回3
  • 嗨 Mohit,您可以删除旧答案并解释您编辑的答案。
猜你喜欢
  • 2023-01-24
  • 1970-01-01
  • 2019-12-22
  • 2012-06-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多