Data structures 如何合并已排序列表的两个半部分
我有一个整数链表,它的前半部分和后半部分是独立排序的。现在我需要合并两部分来创建一个单独的排序链表 样本输入: 输入列表1:Data structures 如何合并已排序列表的两个半部分,data-structures,linked-list,Data Structures,Linked List,我有一个整数链表,它的前半部分和后半部分是独立排序的。现在我需要合并两部分来创建一个单独的排序链表 样本输入: 输入列表1:1->2->3->4->5->1->2 输出:1->1->2->2->3->4->5 输入列表2:1->5->7->9->11->2->4->6 输出2:1->2->4->5->6->7->9->11 预期输出: 1,2,3….这被称为 查找并查找实现细节。查找自然合并排序以获得最佳解决方案:这是合并排序 我将保留两个指针: ptr1指向前半部分的第一个元素 并且ptr2指
1->2->3->4->5->1->2
输出:
1->1->2->2->3->4->5
输入列表2:1->5->7->9->11->2->4->6
输出2:
1->2->4->5->6->7->9->11
预期输出:
1,2,3….这被称为
查找并查找实现细节。查找自然合并排序以获得最佳解决方案:这是合并排序 我将保留两个指针:
ptr1
指向前半部分的第一个元素
并且ptr2
指向下半部分的第一个元素
您将需要一个额外的数组来存储最终列表,当然您可以选择不使用这个额外的数组,但是讨论离主题还很远
1,比较*ptr1
和*ptr2
,如果*ptr1
的值小于*ptr2
,则将该值(即*ptr1
)复制到最终数组中,并让ptr1
向前移动
如果ptr2
的值较小,只需复制*ptr2
并让ptr2
向前移动即可
2,当指针指向最后一个元素后停止,如果前半部分中有5个元素a[0]a[1]a[2]a[3]a[4]
,则当指针指向
a[5]
3,如果前半部分为空,则复制后半部分的其余部分,反之亦然。在使用函数式语言时,我已经做了无数次了,因此我想我可以给您一个简短的解释 如果你把它看作是一个递归过程,你会更容易理解它,但我会给你一个命令式的过程。 您可以从部分列表和空的排序列表开始 然后开始循环,您的部分列表如下所示:
- 都为空,在这种情况下,您的处理完成
- 其中一个为空,将另一个附加到排序列表中
- 两个head元素和列表的尾部,您将比较两个head,将最小的添加到排序列表中,将另一个保留在其原始位置,然后循环使用剩余的列表
int[]merge(int[]left,int[]right){
int[] merge(int[] left, int[] right) {
int[] ret = new int[left.length + right.length];
int i = 0;
int j = 0;
for (; i < left.length & j < right.length;) {
if (left[i] < right[j]) {
ret[i + j] = left[i++];
} else if (left[i] > right[j]) {
ret[i + j] = right[j++];
} else {
ret[i + j] = left[i];
ret[i + j + 1] = left[i];
i++;
j++;
}
}
if (i < left.length) {
copyIntArray(left, i, left.length, ret, ret.length - i);
} else if (j < right.length) {
copyIntArray(right, j, right.length, ret, ret.length - j);
}
return ret;
}
void copyIntArray(int[] src, int startIndex, int endIndex, int[] des, int desStartIndex) {
for (int i = startIndex; i < endIndex; i++) {
des[desStartIndex++] = src[i];
}
}
int[]ret=新int[left.length+right.length];
int i=0;
int j=0;
对于(;i右[j]){
ret[i+j]=右[j++];
}否则{
ret[i+j]=左[i];
ret[i+j+1]=左[i];
i++;
j++;
}
}
如果(i<左.长度){
复制阵列(左,i,左.长度,反向,反向长度-i);
}else if(j<右.长度){
复制阵列(右,j,右.长度,反向,反向长度-j);
}
返回ret;
}
无效复制阵列(int[]src、int startIndex、int endIndex、int[]des、int desStartIndex){
对于(int i=startIndex;i
预期的最终输出是1,2,3
?为什么会这样?简单地说,这与对最初未排序的列表进行排序是一样的,对于这些列表,有很多种。您的链表实现是否提供了迭代器接口和begin()
和end()
样式的函数?在这种情况下,您可以使用std::merge
算法:@billz预期的输出仍然不是很清楚。我假设它是1,1,1,2,2,3,4,4,5,5,6,7,9,11
。但可能是1,2,4,5
,在这种情况下,我们需要一个求交算法。@jogojapan这是两个独立的测试用例。每一个在一个链表中都有两个已排序的组。因此,对于测试用例1,输出为1,1,2,2,3,4,5
,对于测试用例2,输出为1,2,4,5,6,7,9,11
。因此,这是合并排序,而不是设置交集。特定的步骤称为合并,它将两个已排序的列表/数组合并到O(n)中。他可能不需要新的名单。他说他有一个大的列表,上半部分和下半部分是排序的,我说的是两个分开的列表的步骤,这就是重点。如果两者都是实际的链接列表(而不是数组),那就没关系了。该死,在智能手机上输入这些内容太糟糕了。:)这是因为你不能只递归地键入第一个字符,然后再键入其他字符;您需要具有显式回溯的算法。:)