合并排序中的子数组大小

时间:2018-10-16 20:10:52

标签: java arrays algorithm mergesort

我无法理解合并排序中子数组的大小。在以下代码中:

   public void mergeSort(List<Integer> list, int low, int high){

       if(low<high){
           int mid = (high+low)/2;
           mergeSort(list,low, mid);
           mergeSort(list,mid+1,high);
           merge(list, low, mid, high);

       }
   }

   private void merge(List<Integer> list ,int low, int mid, int high){

       int lSize = mid-low+1;
       int rSize = high-mid;
   //etc 
   }

对于子数组的大小,我必须在左边添加1,而在右边的数组不添加1。我知道,如果我们有一个大小为10的数组,索引将是0..9和lSize将是4-0 + 1,rSize是9-4。

我不确定该如何措辞,但是我无法绕开要在其中添加+1的位置缠绕头部,而没有在我的头中进行整个大小为10的示例数组。如果我有一阵子不触摸mergesort,则会忘记在+1的位置添加内容。有没有更简单的方法来记住这一点?谢谢。

2 个答案:

答案 0 :(得分:0)

这是一个例子。假设清单包含10个元素。这是列表中的索引

0 1 2 3 4 5 6 7 8 9

现在,必须将列表分成两半,然后将每一半递归地排序-一半为0 1 2 3 4,另一半为5 6 7 8 9。因此,上半部分必须在4处停止,而下半部分必须在5处开始并在9处结束。

如果计算中途点mid = (9 + 0) / 2,则应该为4.5,但是由于这是整数数学,因此会被截断(不舍入,截断)为4。因此,您使用mid(4)作为上半年的结束,mid + 1(5)作为下半年的开始。

我希望情况会更清楚

答案 1 :(得分:0)

溢出错误

首先,永远不要添加然后划分索引。如果数组很大,并且您接近数组的结尾,则lowhigh索引如果溢出Integer.MAX_VALUE,则总和为负数。然后,将其除以2将得到一个负值,而不是您期望的正值。

这里是a Google blog post about the issue。 Java中的更正方法是(请注意,这是>>>,而不是>>):

int mid = (high + low) >>> 1;

推理

话虽这么说,这是解决问题的艰难方法,然后是解决问题的简单方法。

问题在于如何处理偶数或奇数low和偶数或奇数high值,以使左右两侧的大小始终保持平衡。

让我们创建一个表,其中包含可接受的lSizerSize值,这些值可以适当平衡:

┏━━━━┯━━━━━━━┳━━━━━━━━━━━━┳━━━━━━━━━━━━┓
┃ low ╲ high ┃     4      ┃     5      ┃
┣━━━━━━┷━━━━━╋━━━━━━━━━━━━╇━━━━━━━━━━━━┫
┃     0      ┃ 2/3 or 3/2 │    3/3     ┃
┣━━━━━━━━━━━━╉────────────┼────────────┨
┃     1      ┃    2/2     │ 2/3 or 3/2 ┃
┗━━━━━━━━━━━━┻━━━━━━━━━━━━┷━━━━━━━━━━━━┛

关联的mid值为:

┏━━━━┯━━━━━━━┳━━━┳━━━┓
┃ low ╲ high ┃ 4 ┃ 5 ┃
┣━━━━━━┷━━━━━╋━━━╇━━━┫
┃     0      ┃ 2 │ 2 ┃
┣━━━━━━━━━━━━╉───┼───┨
┃     1      ┃ 2 │ 3 ┃
┗━━━━━━━━━━━━┻━━━┷━━━┛

因此,我们知道它将类似于mid - lowhigh - mid,但我们可能需要对其进行调整。这些总和是否等于您正在使用的总大小?

┏━━━━┯━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━┓
┃ low ╲ high ┃           4           ┃           5           ┃
┣━━━━━━┷━━━━━╋━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━┫
┃     0      ┃ (2 - 0) + (4 - 2) = 4 │ (2 - 0) + (5 - 2) = 5 ┃
┣━━━━━━━━━━━━╉───────────────────────┼───────────────────────┨
┃     1      ┃ (2 - 1) + (4 - 2) = 3 │ (3 - 1) + (5 - 3) = 4 ┃
┗━━━━━━━━━━━━┻━━━━━━━━━━━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━━━━━━━━━┛

因此,我们比需要的位置少一个,因此我们需要在mid - lowhigh - mid上增加一个,但是哪个?好吧,我们为这两个表制作表格并与我们的第一个表格进行比较。

如果将一个添加到mid - low会发生什么?

┏━━━━┯━━━━━━━┳━━━━━┳━━━━━┓
┃ low ╲ high ┃  4  ┃  5  ┃
┣━━━━━━┷━━━━━╋━━━━━╇━━━━━┫
┃     0      ┃ 3/2 │ 3/3 ┃
┣━━━━━━━━━━━━╉─────┼─────┨
┃     1      ┃ 2/2 │ 3/2 ┃
┗━━━━━━━━━━━━┻━━━━━┷━━━━━┛
如您所见,

与我们第一个表中可接受的选项匹配。如果将一个添加到high - mid,会发生什么?

┏━━━━┯━━━━━━━┳━━━━━┳━━━━━┓
┃ low ╲ high ┃  4  ┃  5  ┃
┣━━━━━━┷━━━━━╋━━━━━╇━━━━━┫
┃     0      ┃ 2/3 │ 2/4 ┃
┣━━━━━━━━━━━━╉─────┼─────┨
┃     1      ┃ 1/3 │ 2/3 ┃
┗━━━━━━━━━━━━┻━━━━━┷━━━━━┛

如您所见,那是不平衡的。

因此,我们有mid - low + 1high - mid

容易解决的方法

是否已调试打印lSizerSize值(System.err.printf("L:%d R:%d\n", lSize, rSize);),并将其添加到lSize,然后将其添加到rSize。尝试使用不同的数组大小,看看哪一个平衡左右两侧的效果最佳。