【问题标题】:Java: get all concatenations of List<List<String>>Java:获取 List<List<String>> 的所有连接
【发布时间】:2012-06-20 15:08:51
【问题描述】:

我有一个List&lt;List&lt;String&gt;&gt; 我需要在第一个维度上获取所有可能连接的列表

[ [1,2 ], [1] , [3,4] ]

应该给:

[ 113, 114, 213, 214 ]

我正在尝试 2 个循环,应该可以。

这是我尝试过的:

private static List<String> constructIndexes(List<List<String>> indexList){
    List<String> index = new ArrayList<String>();

    String v="";

    for (int i=0; i< indexList.size(); i++){
        List<String> l =  indexList.get(i);
        for (int j=0; j<l.size(); j++){
            if (index.size()>0){
                for (int k=0; k<index.size(); k++){
                    index.set(k, index.get(k)+l.get(j));
                    // System.out.println(">");
                }
            } else {
                index.add(l.get(j));
            }

        }
    }

    return index;
}

一些初始化代码:

List<List<String>> indexList = new ArrayList<List<String>>();

    List<String> l = new ArrayList<String>();
    l.add("1");
    l.add("2");
    indexList.add(l);
    l = new ArrayList<String>();
    l.add("1");
    indexList.add(l);
    l = new ArrayList<String>();
    l.add("3");
    l.add("4");
    indexList.add(l);

    System.out.println( constructIndexes(indexList));

【问题讨论】:

  • 所以...串联只能走一种方式? (左右而不是左右?)
  • 您这么说,您的代码中什么不起作用?你得到什么你不想要的? (一个错误,意外的输出?)
  • @Lattyware 我同意 ciril 也应该将这些信息放入其中,但代码非常简单,很容易看出问题所在。在他的代码中,数组元素被添加到索引列表中,而不是被连接成一个字符串然后被添加到索引列表中。
  • 更多的是提出好问题的好习惯。

标签: java algorithm


【解决方案1】:

如何保留一些跟踪每个元素的索引的索引计数器,然后进行传统的向左进位,与添加时相同,例如9 + 1 = 10(将​​ 1 向左移动,并设置为 0)。

private static List<String> constructIndexes(List<List<String>> indexList) {
    List<String> index = new ArrayList<String>();
    int n = indexList.size();
    int[] counter = new int[n];
    int[] max = new int[n];
    int combinations = 1;
    for (int i = 0; i < n; i++) {
        max[i] = indexList.get(i).size();
        combinations *= max[i];
    }
    int nMinus1 = n - 1;
    for (int j = combinations; j > 0; j--) {
        StringBuilder builder = new StringBuilder();
        for (int i = 0; i < n; i++) {
            builder.append(indexList.get(i).get(counter[i]));
        }
        index.add(builder.toString());

        counter[nMinus1]++;
        for (int i = nMinus1; i >= 0; i--) {
            // overflow check
            if (counter[i] == max[i]) {
                if (i > 0) {
                    // carry to the left
                    counter[i] = 0;
                    counter[i - 1]++;
                }
            }
        }
    }
    return index;

测试

List<List<String>> test = Arrays.asList(Arrays.asList("1", "2"),
        Arrays.asList("1"), Arrays.asList("3", "4"));
System.out.println(constructIndexes(test));

输出

[113, 114, 213, 214]

【讨论】:

  • 谢谢,如果可能的话,我会在大集合上运行 2 个答案,以检查哪一个可以更快,我会说递归的,你的使用很多检查
  • @ciril 我会说我的会更快,因为方法调用通常比循环检查更昂贵。然而,在对输入 [1]、[1,2]、直到 [1 .. 9] 进行了一些测试之后,似乎这两种实现都需要大约 500 毫秒才能完成工作。
  • ok(可能只需要计算相同或不同的输入 100 次)
【解决方案2】:

由于外部列表(即列表列表)中的列表数量直到运行时才知道,因此您无法预先知道循环的数量。在这种情况下,您需要递归解决方案:

public static void combine(List<List<String>> data, int[] pos, int n, List<String> res) {
    if (n == pos.length) {
        StringBuilder b = new StringBuilder();
        for (int i = 0 ; i != pos.length ; i++) {
            b.append(data.get(i).get(pos[i]));
        }
        res.add(b.toString());
    } else {
        for (pos[n] = 0 ; pos[n] != data.get(n).size() ; pos[n]++) {
            combine(data, pos, n+1, res);
        }
    }
}

这是怎么称呼它的:

List<List<String>> indexList = new ArrayList<List<String>>();
List<String> a = new ArrayList<String>();
a.add("1");
a.add("2");
List<String> b = new ArrayList<String>();
b.add("1");
List<String> c = new ArrayList<String>();
c.add("3");
c.add("4");
indexList.add(a);
indexList.add(b);
indexList.add(c);
List<String> res = new ArrayList<String>();
combine(indexList, new int[indexList.size()], 0, res);
for (String s : res) {
    System.out.println(s);
}

【讨论】:

  • 很好,是的,我想知道它的复杂性,它是子列表大小的产物,所以是的(子列表的数量)循环是必要的
【解决方案3】:

这对你有用吗

 private <T> List<T> getNthCombination(List<List<T>> lists, int n) {

    List<T> nthCombination = new ArrayList<T>(lists.size());

    int nCarry = n;
    for (List<? extends T> list: lists) {
         int lSize = list.size();
         nthCombination.add(list.get(nCarry % lSize));
         nCarry /= lSize;
    }

    return nthCombination;
}

当然,这是一个基本的组合问题,并且有一些库可以处理这类问题。

【讨论】:

    猜你喜欢
    • 2016-02-23
    • 2020-11-22
    • 2018-10-20
    • 1970-01-01
    • 1970-01-01
    • 2021-09-17
    • 2020-03-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多