找到所有组合的更有效方法?

时间:2011-09-02 02:12:30

标签: java algorithm loops collections combinations

假设您有List Strings或其他任何内容,并且您希望生成另一个List,其中包含来自原始strings的两个list的所有可能组合1}}(汇总在一起),除了使用嵌套的for循环将String与所有其他循环结合起来之外,还有更有效的方法吗?

一些示例代码:

 for(String s: bytes) {
            for(String a: bytes) {
                if(!(bytes.indexOf(a) == bytes.indexOf(s))) {
                    if(s.concat(a).length() == targetLength) {
                        String combination = s.concat(a);
                        validSolutions.add(combination);
                    }
                }
            }
        }

随着list原始Strings的大小增加,执行时间变得非常糟糕。

更有效的方法吗?

3 个答案:

答案 0 :(得分:3)

你不能比 O(N ^ 2)更好,因为有很多种组合。但是你可以通过移除indexOf调用来加速你的算法(从 O(N ^ 3)):

for(int i=0; i<bytes.length(); i++) {
    for(int j=0; j<bytes.length(); j++) {
        string s = bytes[i];
        string a = bytes[j];
        if (i != j && s.length() + a.length() == targetLength) {
            validSolutions.add(s.concat(a));
        }
    }
}

答案 1 :(得分:3)

您可以通过设置i != j来避免检查j = i + 1条件。此外,bytes.length()之类的东西会在两个循环的每次迭代中得到评估 - 将其保存为值并重用。在循环内调用a.length()会多次询问相同字符串的长度 - 您也可以在其上保存一些运行时。以下是更新:

int len = bytes.length();
int aLength;
String a, b;
for(int i=0; i<len; i++) {
  a = bytes[i];
  aLength = a.length();
  for(int j=i; j<len; j++) {
    b = bytes[j];
    if (b.length() + aLength == targetLength) {
      validSolutions.add(b.concat(a));
      validSolutions.add(a.concat(b));
    }
  }
}

编辑:j = i,因为您想要考虑字符串与其自身的组合;此外,您还需要添加a.concat(b),因为循环中从不考虑此组合,但它是有效的字符串

答案 2 :(得分:1)

除了Jimmy和lynxoid所说的,总长度受限制的事实可以进一步优化。按照长度的顺序对字符串进行排序,然后对于每个s,您知道只需要a a.length() == targetLength - s.length()。{/ p>

所以一旦你击中一个比你更长的字符串就可以突破内部循环(因为所有其余部分都会更长),你可以从“正确”的地方开始,例如使用下限二进制文件搜索阵列。

复杂性仍然是O(n ^ 2),因为在最坏的情况下,所有字符串都是相同的长度,等于totalLength的一半。通常虽然它应该比考虑所有字符串对要好一些。