Java 获取具有子集的列表的“相邻”值的算法
我有这样一个文本文件:Java 获取具有子集的列表的“相邻”值的算法,java,algorithm,list,subset,Java,Algorithm,List,Subset,我有这样一个文本文件: A B C A = { a1, a2, a3 } B = { b1, b2 } C = { c1, c2, c3 } 每个元素都有一个子集,如下所示: 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
A = { a1, a2, a3 }
B = { b1, b2 }
C = { c1, c2, c3 }
每个元素都有一个子集,如下所示:
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,子集的大小可能不同
我认为这是一个递归函数,有两个索引,可能在数组中的位置和数组的索引,但我真的不知道如何实现所有这些
我甚至试着调整一个函数,用相同的输入做笛卡尔积,但我完全失败了。我不需要生成笛卡尔积
循环遍历所有列表,其中索引是要迭代的列表
找到要迭代的内部列表的大小并循环多次
循环遍历列表始终获取第一个元素,除非列表是要索引的列表,在这种情况下,从迭代列表中获取下一个值。构建基本列表,该列表由每个列表的第一个元素组成。然后循环遍历所有列表的所有元素。对于每个这样的元素,使用该元素在适当的位置更新基本列表,并将更新后的列表添加到列表的运行计数中 我在下面包含了一个示例实现
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);
}
}
}
我的回答假设您已经对数据集进行了排序,并且它们的顺序正确
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();
}
}
每个人都在使用容器,所以我将尝试只使用数组来解决它 在这个算法中,我只打印第1行,然后我将重点放在用剩余子集的第一个元素包围子集的下一个元素上
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();
}
将问题形式化:
这可以映射到多阶段图。只需在谷歌上搜索一个链接,您要做的是打印从超级源“S”到超级接收器“T”的所有路径。你可能想读一下同样的东西。如果您有进一步的兴趣,这也与有关。像a1、b2、c2这样的组合如何-这不是您想要的?这看起来不像笛卡尔积,因为只有8个输出?或者你想要生成的是笛卡尔积?我不需要生成笛卡尔积,只是试着根据我的目的调整函数,但正如我所说的,我失败了。我想要这些:扫描一个数组,保持其他数组不变>当A在末尾时,然后在B数组中传递并执行相同的操作>当B在末尾时,然后在C数组中传递并执行相同的操作,等等@cheeken不幸的是我不想要这样的组合:a1,b3,c1??我不明白b3是从哪里来的,因为它并没有列在你的B子题中,所有的答案。。。但我应该选择哪种解决方案呢?John B发布的这篇文章在资源方面似乎更紧凑、更便宜。。。我错了吗?列表不应该是列表吗?
a1, b1, c1
a2, b1, c1
a3, b1, c1
a1, b2, c1
a1, b1, c2
a1, b1, c3
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();
}