Java加入列表取决于值,

时间:2015-02-25 10:56:09

标签: java list join

数据: 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)时,它将工作数小时。 那么也许有人可以建议更好的解决方案?

2 个答案:

答案 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,因为它不再是优化。