0

我有一个这样的文本文件:

A
B
C

每个元素都有一个像这样的子集:

A = { a1, a2, a3 }
B = { b1, b2 }
C = { c1, c2, c3 }

我想生成这个:

    a1, b1, c1
     a2 , b1, c1
     a3 , b1, c1
    a1, b2 , c1
    a1, b1, c2 
    a1, b1, c3

我不知道文本文件中元素的数量(例如,可能是:A、B、C、D、E),并且子集的大小可能会有所不同。

我只能认为它是一个具有 2 个索引的递归函数,可能是“数组中的位置”和“数组的索引”,但我真的不知道如何实现所有这些。

我什至尝试调整一个使用相同输入进行笛卡尔积的函数,但我完全失败了。我不需要生成笛卡尔积

4

5 回答 5

6

构建“基本列表”,它由每个列表的第一个元素组成。然后遍历所有列表的所有元素。对于每个这样的元素,使用该元素在适当位置更新基本列表,并将此更新的列表添加到列表的运行计数中。

我在下面包含了一个示例实现。

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class AdjacentListGenerator {
    public static <T> List<List<T>> generateAdjacentLists(List<List<T>> lists) {
        List<List<T>> result = new ArrayList<List<T>>();
        List<T> baseList = new ArrayList<T>();

        // Generate the base list, which is comprised of all the first elements
        for (List<T> list : lists) {
            baseList.add(list.get(0));
        }
        result.add(baseList);

        // Loop over each list, and for each element beyond the first, make a
        // copy of the base list, update that element in place, and add it to
        // our result
        for (int list_i = 0; list_i < lists.size(); list_i++) {
            List<T> list = lists.get(list_i);
            for (int listElement_i = 1; listElement_i < list.size(); listElement_i++) {
                List<T> updatedList = new ArrayList<T>(baseList);
                updatedList.set(list_i, list.get(listElement_i));
                result.add(updatedList);
            }
        }

        return result;
    }

    public static void main(String... args) {
        List<String> a = Arrays.asList(new String[] { "a1", "a2", "a3" });
        List<String> b = Arrays.asList(new String[] { "b1", "b2" });
        List<String> c = Arrays.asList(new String[] { "c1", "c2", "c3" });
        List<List<String>> lists = new ArrayList<List<String>>();
        lists.add(a);
        lists.add(b);
        lists.add(c);
        for (List<String> list : AdjacentListGenerator
                .generateAdjacentLists(lists)) {
            System.out.println(list);
        }
    }
}

输出

[a1, b1, c1]
[a2, b1, c1]
[a3, b1, c1]
[a1, b2, c1]
[a1, b1, c2]
[a1, b1, c3]
于 2012-06-15T14:33:50.863 回答
3
List<List<Integer>> myInput = ...

for(int i=0; i<myInput.size(); i++){
     for (int j=0; j<myInput.get(i).size(); j++){
        if (j == 0 && i > 0){
           continue;
        }
        List<Integer> result = new ArrayList<Integer>(myInput.size());
        for(int k=0; k<myInput.size(); k++){
            if (k == i){
               result.add(myInput.get(k).get(j));
            }else{
               result.add(myInput.get(k).get(0));
            }
        }
        System.out.println(result);
     }
}

遍历所有列表,其中索引是要迭代的列表。

找到要迭代的内部 List 的大小并循环多次。

遍历列表总是获取第一个元素,除非列表是被索引的列表,在这种情况下从迭代列表中获取下一个值。

于 2012-06-15T14:26:07.097 回答
2

每个人都在使用容器,所以我将尝试仅使用数组来解决它。

在这个算法中,我只打印第一行,然后我专注于用其余子集的第一个元素围绕子集的下一个元素

String[] lines = { "a1, a2, a3", "b1, b2", "c1, c2, c3" };

String[][] array = new String[lines.length][];
for (int i = 0; i < lines.length; i++)
    array[i] = lines[i].replaceAll(" +", "").split(",");

//lets type 1st row to ignore it in rest algoritm
System.out.print(array[0][0]);
for (int i = 1; i < array.length; i++)
    System.out.print(", " + array[i][0]);
System.out.println();

//in rest of algorithm we must surround each element by 
//1st element or rest rows, so lets iterate over each row
for (int row = 0; row < array.length; row++) 
    //and surround its elements
    for (int col = 1; col < array[row].length; col++) {
        //left surround
        int i=0;
        for (; i<row; i++)
            System.out.print(array[i][0]+", ");
        //
        System.out.print(array[row][col]);
        //right surround
        for (i=i+1; i<array.length; i++)
            System.out.print(", "+array[i][0]);
        System.out.println();
    }
于 2012-06-15T18:56:42.617 回答
1

我的回答假设您已经对数据集进行了排序并且它们的顺序正确。

public class SubsetPrinter
{
  private static final String DELIMITER = ", ";
  private static final String NEWLINE = System.getProperty("line.separator");

  public static String printSubsets(Map<String, List<String>> elements)
  {
    List<String> lines = new ArrayList<String>();
    for (Map.Entry<String, List<String>> entry : elements.entrySet())
    {
      for (String sub : entry.getValue())
      {
        String line = getLine(elements, entry.getKey(), sub);
        if (!lines.contains(line))
        {
          lines.add(line);
        }
      }
    }
    return asString(lines);
  }

  private static String getLine(Map<String, List<String>> elements, String element, String sub)
  {
    StringBuilder line = null;
    for (Map.Entry<String, List<String>> entry : elements.entrySet())
    {
      if (line == null)
      {
        line = new StringBuilder();
      }
      else
      {
        line.append(DELIMITER);
      }
      if (entry.getKey().equals(element))
      {
        line.append(sub);
      }
      else
      {
        line.append(entry.getValue().get(0)); // appends the first 
      }
    }
    return line.toString();
  }

  private static String asString(List<String> lines)
  {
    StringBuilder sb = null;
    for (String line : lines)
    {
      if (sb == null)
      {
        sb = new StringBuilder();
      }
      else
      {
        sb.append(NEWLINE);
      }
      sb.append(line);
    }
    return sb.toString();
  }
}

测试是:

private Map<String, List<String>> getDataSet1()
{
  Map<String, List<String>> map = new HashMap<String, List<String>>();
  List<String> subsetA = Arrays.asList( new String[] { "a1", "a2", "a3" } );
  List<String> subsetB = Arrays.asList( new String[] { "b1", "b2" } );
  List<String> subsetC = Arrays.asList( new String[] { "c1", "c2", "c3" } );
  map.put("A", subsetA);
  map.put("B", subsetB);
  map.put("C", subsetC);
  return map;
}

@Test
public void testPrintSubsets()
{
  Map<String, List<String>> elements = getDataSet1();
  String output = SubsetPrinter.printSubsets(elements);
  System.out.println(output);
}

输出:

a1, b1, c1
a2, b1, c1
a3, b1, c1
a1, b2, c1
a1, b1, c2
a1, b1, c3
于 2012-06-15T15:17:45.397 回答
1

正式化您的问题:

这可以映射到多阶段图。刚刚在网上搜索了多阶段图的图解说明: 您要做的是打印从超级源“S”到超级汇“T”的所有路径。您可能想阅读相同的内容。如果您进一步感兴趣,这也与网络流问题有关。

于 2012-06-15T20:01:30.340 回答