给定一个数组,它有2个部分,每个部分都被排序(例如2 4 6 8 1 3 5),写一个函数使整个数组排序。
要求:
很容易写出O(n 2 )或O(n logn)(使用二进制搜索来查找插入位置)解决方案,我想知道是否有可能获得O( n)解决方案?
答案 0 :(得分:3)
简单的就地合并算法通常会使交换项目冒泡到第二个区域中的正确位置。作为对此的改进,我创建了一个有序的"交换区域"在两个区域之间,新交换项目的位置始终在最后,因此可以更有效地移动到位。
我们从两个已排序的区域开始。 (图1)区域1中的项目从左到右逐个地与区域2中的第一个项目进行比较,并在必要时进行交换。一旦区域1中的项目被交换,它就会在区域1和区域2之间创建一个交换区域。(图2)从那时起,区域1中的项目将与第一个项目进行比较。区域2,以及交换区域中的第一个项目。这会产生两种情况:
当区域1完全合并时,交换区域将成为新区域1,算法将再次与阵列的其余部分一起启动。 (图6)
function mergeInPlace(array) {
var zone2 = 0, swapzone = 0;
// FIND START OF ZONE 2
while (array[zone2] <= array[++zone2]);
// ITERATE OVER ALL ITEMS IN ZONE 1
for (var zone1 = 0; zone1 < zone2; zone1++) {
// WHEN ZONE 1 IS SORTED, TREAT SWAP ZONE AS NEW ZONE 1
if (zone1 == swapzone) swapzone = zone2;
// CHECK WHETHER SWAP ZONE OR ZONE 2 HAS SMALLEST FIRST ITEM
if (array[zone2] <= array[swapzone]) {
// COMPARE AND SWAP WITH FIRST ITEM OF ZONE 2
if (array[zone1] > array[zone2]) {
var temp = array[zone1];
array[zone1] = array[zone2];
array[zone2++] = temp;
}
}
// COMPARE AND SWAP WITH FIRST ITEM OF SWAP ZONE
else if (array[zone1] > array[swapzone]) {
var temp = array[zone1];
array[zone1] = array[swapzone];
// MOVE SWAPPED ITEM TO END OF SWAP ZONE
for (var i = swapzone; i < zone2 - 1; i++) {
array[i] = array[i + 1];
}
array[zone2 - 1] = temp;
}
}
}
var a = [2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,51,1,1,2,3,5,8,13,21,34,55];
mergeInPlace(a);
document.write(a);
&#13;