【问题标题】:Sorting an array continuously连续排序数组
【发布时间】:2012-03-15 16:33:15
【问题描述】:

我有一个用户给了我一个随机的对象数组,我想做一些错误检查,基本上我希望空对象位于数组的末尾,这样数组的中间只由非空对象(对象的排序无关紧要)。

这是我所拥有的,它不起作用。 谁能帮忙。

private void properArray(){
    int i = 0;
    int j;
    int cap = theHeap.length;
    for(; i < (cap-1); i++){
        if (theHeap[i] == null){
            j = i + 1;
            while(j < (cap-1)){
                if(theHeap[j] != null){
                    theHeap[i] = theHeap[j];
                    theHeap[j] = null;
                }
                j++;  
            }
        }
    } 
}

【问题讨论】:

    标签: java arrays object sorting


    【解决方案1】:

    这里有一种更简单的方法可以对这样的数组进行排序:

    Arrays.sort(theHeap, new Comparator() {
      public int compare(Object o1, Object o2) {
        // nulls are "greater" than non-nulls
        if (o1 == null && o2 != null) return 1;
        // non-nulls are "smaller" than nulls
        if (o1 != null && o2 == null) return -1;
        // in all other comparisons, we don't care
        return 0;
      }
    });
    

    或者使用 Java 8:

    Arrays.sort(theHeap, (o1, o2) -> (o1 == null && o2 != null) ?  1
                                   : (o1 != null && o2 == null) ? -1
                                   :                               0);
    

    如果你的类路径中有Apache Commons Collections,你可以用更少的代码来写这个:

    Arrays.sort(theHeap, new NullComparator());
    

    正如 Ted 所提到的,这在 O(n log n) 中执行并创建您的数组的克隆以进行排序...因此它不是最快的解决方案...

    【讨论】:

    • 为什么这个 O(N log N) 操作会更有效率?该任务可以在 O(N) 内完成。
    【解决方案2】:

    无需对数组进行两次迭代。如果您不关心非空对象的顺序(特别是,如果它们不需要保持相同的相对顺序),您可以非常简单地做到这一点:

    int end = theHeap.length;
    for (int i = 0; i < end; ++i) {
        while (theHeap[i] == null && i < end) {
            --end;
            theHeap[i] = theHeap[end];
            theHeap[end] = null;
        }
    }
    

    由于每次循环迭代(外部或内部)将(end - i) 减一,并且当它们相遇时循环结束,这是一个 O(N) 算法。

    EDIT 避免交换空值的修订版本(也许效率更高一些):

    int end = theHeap.length;
    for (int i = 0; i < end; ++i) {
        if (theHeap[i] == null) {
             while (--end > i && theHeap[end] == null) {
                 // loop
             }
             if (i < end) {
                 theHeap[i] = theHeap[end];
                 theHeap[end] = null;
             }
        }
    }
    

    EDIT 2 一个更简单的版本,它还保持非空元素的初始排序顺序:

    int next = 0;
    for (int i = 0; i < theHeap.length; ++i) {
        if (theHeap[i] != null) {
            if (i > next) {
                theHeap[next] = theHeap[i];
                theHeap[i] = null;
            }
            ++next;
        }
    }
    

    【讨论】:

    • 这将失败,输入:["x", null, "y", null]
    • @DilumRanatunga 我修改了代码,但是原来的怎么失败了? (我只是根据您的输入运行它,它运行良好。)
    • 第三版真是一个不错的解决方案!可能是 OP 的最佳选择
    【解决方案3】:

    试试:

    int j = array.length;
    for (int i = 0; i < j; ++i) {
      if (array[--j] == null) {
        continue;
      }
      // array[j] is not null.
      if (array[i] == null) {
        array[i] = array[j];
        array[j] = null;
      }
    }
    

    【讨论】:

    • 这失败了[null, "x", "y", null]
    猜你喜欢
    • 2011-11-19
    • 1970-01-01
    • 2020-09-19
    • 2019-09-15
    • 1970-01-01
    • 2018-08-08
    • 2021-01-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多