【问题标题】:Merge many short sorted lists into a long sorted list efficiently有效地将许多短排序列表合并成一个长排序列表
【发布时间】:2011-10-16 03:00:43
【问题描述】:

我反复将 10000 个排序列表合并为一个长排序列表。每个列表包含大约 5000 个doubles

double[] result;// this is the single long sorted list
void merge(double[] x){
    double[] newList=new double[x.length+result.length];
    int i=0,j=0;
    while(i<x.length && j<result.length){
        insert the smaller one
        increment i or j;
    }
    if(i<x.length){
        add the rest
    }
    if(j<result.length){
        add the rest
    }
    result=newList;
}

此方法每次都分配一个新数组。随着result[] 的增长,这不是有效的。有什么建议吗?

【问题讨论】:

    标签: java arrays list merge


    【解决方案1】:

    你显然有足够的内存来保存整个结果(是 400Mb 吗?)所以大概你可以保存所有的源 800Mb 很大,但不是太大?然后,您可以在开始时快速分配整个答案缓冲区。

    如果您准备使用更多内存,您可以采取“加倍”的方法。

    合并 1 和 2 形成 A1,合并 3 和 4 形成 A2 等直到 A2500(您现在可以丢弃第一级数组)

    然后合并A1和A2形成B1; A3 & A4 组成 B2 到 B1250(你现在丢弃 A 数组)

    依此类推,产生 C1-C625、D1-D313、E1-E157 ... M1,这是最终答案

    这样,任何给定的数字都会移动 15 次,而目前每个数字都移动 5000 次。

    【讨论】:

    • 我认为:“将 1 和 2 合并为 A1,2 和 3 合并为 A2”应改为:“将 1 和 2 合并为 A1,3 和 4 合并为 A2”?
    • 没有必要花哨。 OP 具有已知数量的数组和已知数量的元素。如果空间不是问题,将所有元素添加到树中,然后将树转换回列表。这将是空间效率低下,但时间效率高。如果时间不是问题,在每个列表的“头部”找到最小的元素并添加它。时间复杂度会很糟糕,但空间会尽可能高效。这是一个“随便做”的问题。
    【解决方案2】:

    将您的问题视为merge-sort 的合并部分。创建 2 个足够大的数组来保存所有组合的小列表的内容。然后在合并步骤中将它们交替用于源存储和目标存储。

    【讨论】:

      【解决方案3】:

      您可以像 ArrayList 一样处理它,每次需要重新分配时将数组的长度加倍,然后仅在空间不足时重新分配。尽管最后您可能有相当多的剩余空间,但由于分配较少,您将节省处理时间。然后只需与 Result 和 X 进行就地合并。

      【讨论】:

        猜你喜欢
        • 2013-11-10
        • 1970-01-01
        • 2011-09-26
        • 1970-01-01
        • 2013-10-18
        • 1970-01-01
        • 2014-12-02
        • 2011-05-17
        • 2015-05-12
        相关资源
        最近更新 更多