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

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

我有两组未排序的整数:集合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中删除一个整数并插入setA
  • 有没有更好的方法在Java中实现这一点?如果可能,我想删除“while循环中的排序”。

    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。原始算法根本不会迭代,而您的算法会。同意-我不确定他的算法是否能解决问题,所以我决定坚持问题标题中给出的问题;)