Java 如何根据时间和内存高效地生成集合元素组合的总和?
我有一个随机的整数集S,这个集的基数(n)可能从10到1000不等。我需要存储从该集合生成的大小为r的nCr组合的所有总和。通常r的范围是3到10 例如,如果S={1022333444425446137128983697657,12}和r=4,那么生成的和将是{0,1,2,3}=102+233+344+442,{0,1,2,4}=102+233+344+544 我在Java中实现了一个findCombi函数(如下),该函数根据r大小的索引集为我提供了所有nCr组合,然后我在另一个函数中筛选这些集合以生成相应元素的总和。 但是程序给出了heapspace错误,可能是因为指数性质,我有100-5000个这样的集合,或者可能是内存泄漏 有没有一种更快、消耗更少内存的方法 注:dsize=n,combiSize=rJava 如何根据时间和内存高效地生成集合元素组合的总和?,java,combinations,heap-memory,Java,Combinations,Heap Memory,我有一个随机的整数集S,这个集的基数(n)可能从10到1000不等。我需要存储从该集合生成的大小为r的nCr组合的所有总和。通常r的范围是3到10 例如,如果S={1022333444425446137128983697657,12}和r=4,那么生成的和将是{0,1,2,3}=102+233+344+442,{0,1,2,4}=102+233+344+544 我在Java中实现了一个findCombi函数(如下),该函数根据r大小的索引集为我提供了所有nCr组合,然后我在另一个函数中筛选这些集
List findCombi(int-dsize,int-combiSize){
如果((组合大小==0)| |(dsize==0)){
返回null;
}
长n=dsize;
int r=组合;
对于(int i=1;i我之前需要类似的东西,所以这里有一些代码改编自我当时做的项目。allSums方法构建了一个大小为r的索引列表,用于表示所有可能的组合。在每一步,当前和被添加到结果集中,然后生成下一个组合。因为结果是p但在一个集合中,一个结果不可能出现两次。我包括了一个主要的方法,所以你可以看到它的工作。我希望这是明确的,请随意提问
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);
}
}
import java.util.*;
公共课程{
静态私有集allSums(列表值,int r){
HashSet res=新的HashSet();
if((values.isEmpty())| | r>values.size()){
返回res;
}
//建立索引列表
List li=new ArrayList();
对于(int i=0;i=0)和&(li.get(i)==li.get(i+1)-1)){
我--;
}
//是否找到了这样一个索引?
如果(i==-1){
break;//如果没有,就结束了
}
//增加最后一个索引,并将所有下一个索引设置为其初始值
li.set(i,li.get(i)+1);
对于(int j=i+1;j
}这个问题可能应该移到。你的例子中不是指r=4
吗?@barakmanos谢谢你的更正!我已经编辑过了。你可以通过简单地计算一个元素将出现的组合数量来数学地解决这个问题。因为这对于任何元素都是一样的,所以你的问题现在简化为计算t原始集合的总和并将其与此数字相乘。您可以将代码移动到迭代器中,并在请求时创建组合。这样,您就不必将所有列表保留在内存中。
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);
}
}