寻找从2个列表中查找排序顺序的有效方法

时间:2009-09-24 02:33:30

标签: java algorithm

我有2组未排序的整数:设置A和设置B.但我们不知道setB中有多少项目。

我需要:

while setA and setB are not empty:
    pop the smallest no from setA
    move an int from setB to setA

在Java中最有效的方法是什么?

我在想

  1. 为setA创建一个ArrayList,为setB创建一个LinkedList
  2. while(setA和setB不为空) 排序(组A) pop setA 从setB中删除一个整数并插入setA
  3. 在Java中有更好的方法吗?如果可能的话,我想删除'while循环中的排序'。

3 个答案:

答案 0 :(得分:1)

TreeSet<Integer> setA = new TreeSet<Integer>(listA);
TreeSet<Integer> setB = new TreeSet<Integer>(listB);
while (!setA.isEmpty()) {
    setA.remove(setA.first());
    if (!setB.isEmpty()) {
        Integer first = setB.first();
        setB.remove(first);
        setA.add(first);
    }
}

说明:TreeSet类在红黑树中维护集合,该树在集合元素的自然顺序上排序;即在这种情况下的Integer.compareTo()方法。添加或删除元素会在元素的树中找到适当的位置,然后添加或删除它,而无需进行排序。

isEmpty方法是O(1),firstaddremove方法都是O(log N),其中每个都必须被调用O(N)次。创建初始树集也是O(N log N)。所以整体复杂性将是O(N log N),其中N是总列表大小。

答案 1 :(得分:0)

以下是我从问题中理解的内容:我们需要一个包含setA和setB中所有元素的已排序集合。因为setA和setB可能包含相同的项,所以我们应该使用一个列表(保留重复项)。如果我们不想要重复,只需通过TreeSet交换ArrayList并删除额外的排序。

我假设两个集合包含相同类型的元素 - 如果没有,我们仍然可以使用Collections.sort但必须将Comparator推送到能够比较不同类型对象的sort方法。

private Collection<Integer> combineAndSort(Set<Integer>...sets) {
   Collection<Integer> sorted = new ArrayList<Integer>();
// Collection<Integer> sorted = new TreeSet<Integer>();
   for(Set<Integer> set:sets) {
      sorted.addAll(set);
   }
   Collections.sort(sorted); // obsolete if using TreeSet 
}

答案 2 :(得分:0)

如果您使用的是Java 5,请考虑java.util.PriorityQueue

Collection<Integer> setA = ...;
Collection<Integer> setB = ...;
if (setA.isEmpty()) {
  // if A is empty, no need to go on.
  return;
}
PriorityQueue<Integer> pq = new PriorityQueue<Integer>(setA);
Iterator<Integer> iterB = new LinkedList<Integer>(setB).iterator();
// no need to check if A is empty anymore: starting off non-empty,
// and for each element we remove, we move one over from B.
while (iterB.hasNext()) {
  int smallest = pq.poll();
  doStuffWithSmallest(smallest);
  pq.add(iterB.next());
  iterB.remove();
}

请注意,在上面的代码中,我首先将setB包装在链表中以支持有效删除。如果你的setB支持有效删除,你不需要包装它。 另请注意,由于您不关心从setB的 front 移动元素,因此ArrayList可以支持非常有效的删除:

private <T> T removeOne(ArrayList<T> array) throws IndexOutOfBoundsException {
  return array.remove(array.size() - 1);
}