【问题标题】:Fastest way to get all combinations of numbers in array without gaps获得数组中所有数字组合而没有间隙的最快方法
【发布时间】:2014-10-26 07:06:10
【问题描述】:

我需要从数组中每个可能的数字组合计算总和(单独的总和,而不是一个总和)。组合不能跳过数字,所以:

对于 y > x,您需要将 a[x] 和 a[y] 之间的每个数字相加。

对于 n 大小的数组,您有 (n)+(n-1)+(n-2)+...+1 ,因此对于 n = 5,有 15 种组合。

我需要尽快完成,空间不是问题。

编辑:我试过了:

unsigned long long r_all = 0;
std::vector<int> g_seentimes(m);

for(int i = 0; i<n; i++)
    r_all += w[z];
    if(r_all > r){
        r = r_all;
    }
}

for(int j = 0; j<n; j++){

    unsigned long long r_temp = r_all;

    for(int i = 0; i<(n-j); i++){

        r_temp -= w[n-i];

        if( r_temp > r){
            r = r_temp;
        }
    }

    r_all -= w[y];

    if( r_all > r){
            r = r_all;
    }

}

for(int i = 0; i < n; i++){
    unsigned long long r_temp = 0;
    for(int j = 0; j<(n-i); j++){
        r_temp += w[i+j];
        if(r_temp > r){
            r = r_temp;
        }
    }
}
//r is the answer

编辑 2: 预期的输出是最大可能的数字,但是我提供的例子是简单的版本,最初如果有两个或多个相同数字的组合,你不添加其中任何一个的值,所以 {5, 3, 5, 3, 1} = 1,但 {5, 3, 1} = 9。我已经弄清楚了,只需要尽可能快的方法来完成所有组合。

编辑 3: @Tuan333被问及组合的数量,我认为它会更容易显示:

X- chosen, x-unchosen
n = 5

XXXXX    XXXXx    XXXxx    XXxxx    Xxxxx
xXXXX    xXXXx    xXXxx    xXxxx
xxXXX    xxXXx    xxXxx
xxxXX    xxxXx
xxxxX

【问题讨论】:

  • 2 个嵌套的 for 循环。第一个选择组合的大小,第二个在里面添加数字..?
  • 你需要展示你的尝试。
  • 你能提供一个预期输出的小例子吗?我给了你一个 +1 来编辑你的问题。 :)
  • 当你说每个可能的数字组合时,那么对于 n 个数字,应该有 2^n 个组合,而不是 n*(n+1)/2 个组合(因此如果 n = 5,应该是 2^5,而不是 15 种组合)。给定一组 n 个数字,有 n*(n+1)/2 种方法可以从原始的 n 个数字集中选择一组两个数字。你追求的是哪一个?任何数字组合的总和或任意 2 个数字的总和?

标签: c++ arrays algorithm


【解决方案1】:

首先制作一个累积部分和的数组。所以如果你的号码是a = [1, 2, 3, 4, 5],那么这个数组就是b = [0, 1, 3, 6, 10, 15]。 (请注意,我在开头包含了空总和,因此第二个数组更大。

现在观察,aith 到 jth 元素的总和是 b[j+1] - b[i]。所以现在你可以做一个双循环。

【讨论】:

    【解决方案2】:

    不像@btilly 的解决方案那样优雅,但这里有一种直观的方式来生成您需要的所有序列:

    X- chosen, x-unchosen
    n = 5
    
    Xxxxx
    xXxxx
    xxXxx
    xxxXx
    xxxxX
    
    XXxxx
    xXXxx
    xxXXx
    xxxXX
    
    XXXxx
    xXXXx
    xxXXX
    
    XXXXx
    xXXXX
    
    XXXXX
    

    对于每个“块”,您可以跟踪子序列中的数字数量(我们称之为 blockLength)。然后你只需要遍历你的原始数组来获得所需的子序列,注意如果你当前的子序列有长度blockLength,那么你需要在第(原始数组长度-blockLength)项处终止。这是生成所有子序列的代码(Java)。如果有重复的数字,您可以通过预处理将它们全部删除。

    int[] a = {5,3,1};
    for(int subSeqLength = 1; subSeqLength <= a.length; subSeqLength++){
        for(int j = 0; j + subSeqLength <= a.length; j++){
            for(int k = j; k <j+subSeqLength; k++)
                System.out.print(a[k]+" ");
            System.out.println();
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2022-12-21
      • 1970-01-01
      • 2012-02-26
      • 2021-01-25
      • 2011-10-10
      • 1970-01-01
      • 2011-08-14
      • 2015-04-18
      • 1970-01-01
      相关资源
      最近更新 更多