Java 寻找从2个列表中查找排序顺序的有效方法
我有两组未排序的整数:集合A和集合B。但我们不知道在setB中提前有多少项 我需要:Java 寻找从2个列表中查找排序顺序的有效方法,java,algorithm,Java,Algorithm,我有两组未排序的整数:集合A和集合B。但我们不知道在setB中提前有多少项 我需要: while setA and setB are not empty: pop the smallest no from setA move an int from setB to setA 在Java中最有效的方法是什么 我在想 创建setA的ArrayList和setB的LinkedList while(setA和setB不为空) 排序(setA) 流行毛 从setB中删除一个整数并插入se
while setA and setB are not empty:
pop the smallest no from setA
move an int from setB to setA
在Java中最有效的方法是什么
我在想
TreeSet setA=new TreeSet(listA);
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);
}
}
树集setB=新树集(列表b);
而(!setA.isEmpty()){
setA.remove(setA.first());
如果(!setB.isEmpty()){
整数first=setB.first();
退刀(第一次);
setA.add(第一);
}
}
说明:TreeSet类在一棵红黑树中维护集合,该树按照集合元素的自然顺序排序;i、 e.本例中的Integer.compareTo()
方法。添加或删除元素会在树中找到该元素的适当位置,然后添加或删除该元素而无需排序
isEmpty
方法是O(1),而first
、add
和remove
方法都是O(logn),其中每个方法都必须调用O(N)次。创建初始树集也是O(N logn)。因此,总体复杂性将是O(N log N),其中N是总列表大小。我从这个问题中了解到:我们需要一个包含setA和setB中所有元素的排序集合。因为setA和setB可能包含相等的项,所以我们应该使用一个列表(保留重复项)。如果我们不想重复,只需按树集交换ArrayList并删除额外的排序
我假设两个集合都包含相同类型的元素——如果不是,我们仍然可以使用Collections.sort,但必须将比较器推送到能够比较不同类型对象的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
}
private Collection combineAndSort(集合…集合){
集合排序=新的ArrayList();
//集合排序=新树集();
用于(集合:集合){
排序。添加全部(集合);
}
Collections.sort(sorted);//如果使用TreeSet,则会过时
}
如果你使用java 5,请考虑<代码> java .UTI.PrimyItQuey:
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();
}
Collection setA=。。。;
集合setB=。。。;
if(setA.isEmpty()){
//如果A为空,则无需继续。
返回;
}
优先级队列pq=新的优先级队列(setA);
迭代器iterB=新链接列表(setB).Iterator();
//无需再检查A是否为空:从非空开始,
//对于我们移除的每一个元素,我们从B移走一个。
while(iterB.hasNext()){
int最小值=pq.poll();
最小的(最小的);
pq.add(iterB.next());
iterB.remove();
}
请注意,在上面的代码中,我首先将setB包装在一个链接列表中,以支持有效的删除。如果您的setB支持高效删除,则无需对其进行包装。
还请注意,由于您不关心从setB的前面移动图元,因此ArrayList可以支持非常高效的删除:
private <T> T removeOne(ArrayList<T> array) throws IndexOutOfBoundsException {
return array.remove(array.size() - 1);
}
private T removeOne(ArrayList数组)引发IndexOutOfBoundsException{
返回array.remove(array.size()-1);
}
似乎不需要按顺序从setB中删除项,因此您可以避免创建新的树集,而只需在setB中使用迭代器,在检索项时将其删除。@Ken:True。。。但另一方面,从问题中不清楚输入是否真的是不确定顺序集(例如哈希集)或列表。在前一种情况下,将“挫折”设置为树集会导致更可预测的结果。问题尚不清楚。为什么我们需要把int从B移到A?这一切行动的目的是什么?o_O@Andreas:虽然我不理解OP算法的基本原理,但您的代码与他的算法做的事情不同。是的,证明差异的最简单方法是使用非空a和空B。原始算法根本不会迭代,而您的算法会。同意-我不确定他的算法是否能解决问题,所以我决定坚持问题标题中给出的问题;)