[英]How to generate sums of combinations of elements of a set efficiently in terms of time and memory?
我有一個整數的隨機集合S ,並且該集合的基數( n )可能在10到1000之間變化。我需要存儲從該集合生成的大小為r的nCr組合的所有和。 通常r的范圍是3到10。
例如,如果S = {102,233,344,442,544,613,71289,836,97657,12}且r = 4,則生成的總和將為{0,1,2,3} = 102 + 233 + 344 + 442,{0,1,2 ,4} = 102 + 233 + 344 + 544,....等等。
我在Java中實現了findCombi函數(如下),該函數根據r大小的索引集為我提供了所有nCr組合,然后在另一個函數中篩選這些集以生成相應元素的總和。 但是程序給出堆空間錯誤,可能是由於指數性質,我有100-5000個這樣的集合S。 還是可能存在內存泄漏?
有沒有更快,更少內存消耗的方法呢?
注意: dsize = n , combiSize = r
List <List<Integer>> findCombi(int dsize,int combiSize) {
if( (combiSize==0) || (dsize==0) ){
return null;
}
long n=dsize;
int r=combiSize;
for(int i=1;i<combiSize;i++) {
n=n*(dsize-i);
r=r*i;
}
int totalcombi=(int) n/r;
List <List<Integer>> combiData=new ArrayList<>(totalcombi);
int pos;
List <Integer> combi=new ArrayList<>(combiSize);
for(int i=0;i<combiSize;i++) {
combi.add(i,i);
}
combiData.add(new ArrayList<>(combi));
pos=combiSize-1;
while(true) {
if(combi.get(pos)<(dsize-combiSize+pos)) {
combi.set(pos,combi.get(pos)+1);
if(pos==(combiSize-1)) {
combiData.add(new ArrayList<>(combi));
}
else {
combi.set(pos+1,combi.get(pos));
pos++;
}
}
else {
pos--;
}
if(pos==-1) {
break;
}
}
return combiData;
}
我之前需要類似的東西,所以這里有一些代碼是從我當時所做的項目改編而來的。 allSums方法構建大小為r的索引列表,該列表用於表示所有可能的組合。 在每個步驟中,將當前總和添加到結果集中,然后生成下一個組合。 由於結果放在一組中,因此結果不可能出現兩次。 我提供了一種主要方法,因此您可以看到它的工作原理。 我希望這很清楚,隨時提出問題。
import java.util.*;
public class Program {
static private Set<Integer> allSums(List<Integer> values, int r) {
HashSet<Integer> res = new HashSet<>();
if ((values.isEmpty()) || r > values.size()) {
return res;
}
// build the list of indices
List<Integer> li = new ArrayList<>();
for (int i = 0; i < r; i++) {
li.add(i);
}
li.add(values.size()); // artificial last index : number of elements in set
while (true) {
// add the current sum to the result
int sum = 0;
for (int i = 0; i < r; i++) {
sum += values.get(li.get(i));
}
res.add(sum);
// move to the next combination
// first, find the last index that can be incremented
int i = r-1;
while ((i >= 0) && (li.get(i) == li.get(i+1)-1)) {
i--;
}
// was such an index found ?
if (i == -1) {
break; // if not, it's over
}
// increment the last index and set all the next indices to their initial value
li.set(i,li.get(i)+1);
for (int j = i+1; j < r; j++) {
li.set(j, li.get(j-1)+1);
}
}
return res;
}
public static void main(String[] args) {
List<Integer> values = new ArrayList<>();
values.add(10);
values.add(100);
values.add(1000);
values.add(10000);
values.add(100000);
Set<Integer> s = allSums(values, 3);
for (int i : s) {
System.out.println(i);
}
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.