数据:
List<List<int>> startList
- 列出填充的整数列表,内部列表主要有2个元素,如:{[1,2], [2,3],[3,1]}
;
任务: 需要编写将加入innerLists的算法,其中list元素的最后一个等于list的第一个元素。
示例:
List<List<int>> startList = {[1,2],
[2,3],
[4,7],
[7,4],
[3,1],
[6,2],
[3,2],}
,结果应为:{[1,2,3,1],[1,2,3,2],[4,7,4],[6,2]}
至于我,我可以使用以下几个维度循环找到如何做到这一点:
while(true)
{
...
for (List<String> list : startList)
{
...
for (List<String> list : startList)
{
...
}
}
}
但这是非常糟糕的解决方案,因为当它是批量数据(如5000 inerLists)时,它将工作数小时。 那么也许有人可以建议更好的解决方案?
答案 0 :(得分:1)
此代码段在一次迭代中执行,因此顺序为O(N)。请尝试使用您的数据集运行,并告诉我是否有任何问题。
public class Test {
public static void main(String[] args) {
List<List<Integer>> list = new ArrayList<List<Integer>>();
List<Integer> one = new ArrayList<Integer>();one.add(1);one.add(2);
List<Integer> two = new ArrayList<Integer>();two.add(2);two.add(3);
List<Integer> three = new ArrayList<Integer>();three.add(3);three.add(1);
List<Integer> four = new ArrayList<Integer>();four.add(4);four.add(7);
List<Integer> five = new ArrayList<Integer>();five.add(7);five.add(4);
List<Integer> six = new ArrayList<Integer>();six.add(6);six.add(2);
list.add(one);list.add(two);list.add(three);list.add(four);list.add(five);list.add(six);
System.out.println(list);
List<List<Integer>> output = new ArrayList<List<Integer>>();
for(int i=0;i<list.size();i++)
{
List<Integer> current = list.get(i);
List<Integer> last = output.size() == 0 ? null : output.get(output.size()-1);
if(null != last)
{
if(current.get(0)==last.get(last.size()-1))
{
last.addAll(current.subList(1, current.size()));
output.set(output.size()-1, last);
}
else
{
output.add(current);
}
}
else
{
output.add(current);
}
}
System.out.println(output);
}
}
答案 1 :(得分:0)
这似乎可以满足您的需求 - 至少它可以生成您为测试输入所声明的输出。我希望我能正确地解释你的需求。
我没有在last == first
停止响铃,因为这与您的预期输出不符。当它接触到已经访问过的条目时,我已经停止了响铃。查看您的示例 - 您的条目[6,2]
永远不会回到6
,因此永远不会停止。
// Finds which entry in the list is the target of the specified entry.
private int findTarget(List<List<Integer>> list, int pos) {
// Look for that value.
int targetValue = list.get(pos).get(1);
for (int i = 0; i < list.size(); i++) {
if (list.get(i).get(0) == targetValue) {
return i;
}
}
return -1;
}
private List<List<Integer>> findAllRings(List<List<Integer>> list) {
// Maintain a BitSet to keep track of all visited nodes.
BitSet visited = new BitSet(list.size());
// The rings.
List<List<Integer>> rings = new ArrayList<>();
// Carry on until all entries have been visited.
int start = 0;
while (start < list.size()) {
// Where we are in the list.
int pos = start;
// Grow a new ring.
List<Integer> ring = new ArrayList<>();
// Stop when we touch one we have already seen.
boolean ringClosed;
do {
// The value to add.
ring.add(list.get(pos).get(0));
// Stop if it already was set.
ringClosed = visited.get(pos);
// Track it's visited.
visited.set(pos);
if (!ringClosed) {
// Move pos.
pos = findTarget(list, pos);
if (pos < 0) {
// No next pair - break this ring.
ringClosed = true;
}
}
} while (!ringClosed);
// One ring!
rings.add(ring);
// All done - move i forward until we find an unvisited node.
while (start < list.size() && visited.get(start)) {
start += 1;
}
}
return rings;
}
public void test() {
List<List<Integer>> startList = new ArrayList<>(Arrays.asList(
Arrays.asList(new Integer[]{1, 2}),
Arrays.asList(new Integer[]{2, 3}),
Arrays.asList(new Integer[]{3, 1}),
Arrays.asList(new Integer[]{4, 7}),
Arrays.asList(new Integer[]{7, 4}),
Arrays.asList(new Integer[]{6, 2}),
Arrays.asList(new Integer[]{6, 3}),
Arrays.asList(new Integer[]{9, 9})
));
List<List<Integer>> resultList = findAllRings(startList);
for (List<Integer> result : resultList) {
System.out.println(result);
}
}
打印:
[1, 2, 3, 1]
[4, 7, 4]
[6, 2]
[6, 3]
[9, 9]
按要求。
修改:使用Map
删除内循环的需要。我们现在应该大约是O(n)
。
修改:更改BitSet
的使用情况以记录该对的偏移量,而不是该对中第一个条目中的值 - 停止BitSet
爆炸为真实int
值。
删除了Map
,因为它不再是优化。