我正在为以下问题寻找更好的解决方案(明智的时间和复杂性):
给出整数列表。首先打印所有第一个元素,然后是所有第二个元素,依此类推。
示例:{{1,2,3}, {5,4,6}}
打印1,5,2,4,3,6
解决方案1:我可以使用两个for循环迭代列表列表,但是时间复杂度将增加到O(n^2)
。有没有更好的方法来使用O(n)
来实现上述结果?
答案 0 :(得分:1)
简短回答:否。
答案很长:说你想在一个循环中完成它。如果所有内部列表具有相同的长度,和如果您对列表元素(例如数组列表)具有快速随机访问权限,则可以计算下一个元素的位置。伪Java的代码:
int totalElements = outerListSize * innerListSize;
for(int targetPos = 0; targetPos < totalElements; targetPos++) {
//For the outer list, choose the next index until reaching
//the end, then roll over
int outerIndex = targetPos % outerListSize;
//For the inner lists, choose 0 until the outer lists roll
//over, then 1, ...
int innerIndex = targetPos / outerListSize;
targetList.add(targetPos, outerList.get(outerIndex).get(innerIndex));
}
但是这不会为你节省任何东西,因为现在你有一个从0到n * n的单循环 - 你还有O(n2)
答案 1 :(得分:0)
嗯,一切都取决于你n
的意思。
通常n
是输入的大小,在你的情况下,输入的大小是所有列表中所有元素的数量(所有列表大小的总和),然后有线性解决方案需要O(n)
,因为你只访问每个元素一次。
这是我的实现,但是有多种方法可以执行此操作,我假设您声称需要O(n^2)
时间的解决方案实际上也是线性的并且需要O(n)
。
List<List<Integer>> list = new ArrayList<>();
list.add(Arrays.asList(1, 2, 3));
list.add(Arrays.asList(5, 4, 6));
Map<Integer, List<Integer>> map = new HashMap<>();
for (List<Integer> integers : list) {
for (int i = 0; i < integers.size(); i++) {
map.computeIfAbsent(i, k -> new ArrayList<>()).add(integers.get(i));
}
}
int i = 0;
while (map.containsKey(i)) {
for (Integer value : map.get(i)) {
System.out.print(value + ", ");
}
++i;
}
但是,如果我错了并且您将n
定义为列表数量,那么我们就会遇到问题,因为列表大小是独立的列表数量。因此,假设在最坏的情况下,您的一个内部列表的大小为m
,那么整体复杂度为O(nm)
。而且您显然无法做到这一点,因为您总体上{{1}元素,你需要访问列表中的每个元素来打印它。
我认为您无法估算将O(nm)
定义为多个列表的算法复杂度,而无需为每个列表定义最坏情况的元素数。