分治策略合并多个排序数组

Posted

技术标签:

【中文标题】分治策略合并多个排序数组【英文标题】:Divide and conquer strategy to merge multiple sorted arrays 【发布时间】:2015-11-20 01:07:45 【问题描述】:

使用分而治之的策略如何将 k 个已排序的数组合并为一个由 k*n 个元素组成的数组?

到目前为止的理解:我对分而治之的步骤有所了解:

将数组列表分成两个列表,每个列表有 k/2 个数组。递归合并 2 个列表中的数组,最后将生成的 2 个排序数组合并到输出数组中。

需要一些想法和帮助!

public int[] merge(int[][] arrays)
int k = arrays.length;
int n = arrays[0].length;
if size(arrays) == 1:
return arrays.pop()
else
// For longer lengths split the array into two
  int half = arrays.length / 2;
  int[] first_Half = new int[half];
  int[] second_Half = new int[lists.length - half];  
  return merge(merge(first_half),merge(second_half));

我尝试将 2-Dim 数组作为列表列表传递,并将我的前半部分和后半部分更改为 2 Dim。数组按照建议,但我收到错误:“Merge 类型中的方法 kWayMerge(List<List>) 不适用于 kwayMerge 方法上的参数 (int[][])

以下是所做的更改,对于常规合并,我可以使用 Arrays.copyOfclone() 方法吗?

// solve the problem separately in each sub-array
            List a = kWayMerge(firstHalf);

// K-merge operation using divide and conquer strategy

     public int[] kWayMerge(List<List>array) // gets a list of lists as input 
            int[][] firstHalf; int[][] secondHalf;
            if(array.size() == 1) return null; // if currently have 1 array, return it - stop clause
    else 
        int half = array.size()/2;
        firstHalf = new int[half][];
        secondHalf = new int[array.size()-half][];
        // solve the problem separately in each sub-array
        List a = kWayMerge(firstHalf);

    
     return merge((firstHalf ),(secondHalf));   


public int[] merge(int[][] arr1, int[][] arr2) 

    return null;

【问题讨论】:

你的想法很好,是什么阻止了你实现它? 目前我正在尝试测试算法,但我在最后一次合并时遇到错误,要求将合并方法的参数从 2-Dim 更改为单个 Dim 但是我想传递 2-Dim 数组 【参考方案1】:

分而治之的方法是使用递归函数k-way-merge(),获取列表列表作为输入,并在每一步:

如果您当前有 1 个数组,请将其返回(停止子句) 否则,将列表列表拆分为两个,并为每一半 - 递归调用 k-way-merge()。合并两个结果列表。

您需要在代码中更改的主要方面是:

  int[] first_Half = new int[half];
  int[] second_Half = new int[lists.length - half];  

在这里,您需要将first_halfsecond_half 设为int[][],因为它们实际上是列表列表。

另外,在最后一行:

return merge(merge(first_half),merge(second_half));

请注意,外部merge() 是不同的,它不是递归调用 - 而是对“常规”merge() 的调用,它将两个数组合并为一个(因为代码中缺少有关如何执行此操作的逻辑,我假设你已经实现了这样的merge())。

除此之外,该方法看起来是正确的,但效率有点低,因为您每次迭代都复制int[][] 对象,而不是使用索引来“记住您在哪里”。

【讨论】:

@amit 你能否再解释一下这个算法的时间和空间复杂度?

以上是关于分治策略合并多个排序数组的主要内容,如果未能解决你的问题,请参考以下文章

2_3 递归与分治策略(二分搜索技术)

选第k小元素:特定分治策略

快速排序算法

算法导论第2章 分治法与归并排序, 二分查找法

归并排序-marge-sort

基础算法 分治法之合并排序