我有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中最有效的方法是什么?
我在想
在Java中有更好的方法吗?如果可能的话,我想删除'while循环中的排序'。
答案 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),first
,add
和remove
方法都是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);
}