【发布时间】:2013-01-23 13:34:55
【问题描述】:
给定一个数组,该数组的元素按升序排列,直到最大值,然后按降序排列。
Eg. int a[] = { 10, 12, 14, 16, 15, 13, 11}.
这个数组如何高效排序?
数组需要就地排序。
【问题讨论】:
-
数组需要就地排序。
-
将此添加到问题中 - 您应该可以对其进行编辑
给定一个数组,该数组的元素按升序排列,直到最大值,然后按降序排列。
Eg. int a[] = { 10, 12, 14, 16, 15, 13, 11}.
这个数组如何高效排序?
数组需要就地排序。
【问题讨论】:
找到最大值,然后将数组反转到该值。然后对两个子数组应用合并 - 第一个包含最大值,然后是其余数组。这将具有线性计算复杂度,并且需要线性附加内存。
在你的情况下:
a[] = { 10, 12, 14, 16, 15, 13, 11} => {10,12,14,16}, {15,13,11}
=> 反向(线性,就地)=>
{16,14,12,10}, {15,13,11}
=> 合并(线性,附加线性内存)=>
{16,15,14,13,12,11,10}
编辑:关于如何在没有额外内存的情况下合并两个数组,请查看this answer
【讨论】:
我的解决方案:
获取 2 个指针数组开始和数组结束。
从两个指针中写入一个最小值(如果需要降序排序,则为最大值)到结果数组中,然后移位 指向 1 位置的指针(开始指针 +1 位置和结束指针 -1 位置
重复直到开始指针位于结束指针之后。
解的复杂度为 O(N)。 所需内存为 O(N)
伪代码:
function Sort(a)
{
startPointer = 0;
endPointer = a.length-1;
result = new Array of size a.length
while (startPointer <= endPointer)
{
var newValue;
if (a[startPointer] < a[endPointer])
{
newValue = a[startPointer];
startPointer +1
}
else
{
newValue = a[endPointer];
endPointer -1
}
result[a.length - startPointer - endPointer] = newValue;
}
return result;
}
更新问题的解决方案:
作为解决方案使用数组第一部分的部分排序。
指针(10 和 11) {10、12、14、16、15、13、11}
指针(12 和 11) 交换 12 和 11 {10、11、14、16、15、13、12}
指针(14 和 12) 交换 14 和 12 {10, 11, 12, 16, 15, 13, 14} // 将指针从 14 移动到 13 一个较小的位置。
现在我们已经对 {10, 11, 12} 和 {16, 15, 13, 14} 的子问题进行了排序(子问题的 N 减少了两倍)
这个算法的复杂度是:O(N) + (N/2) + O(N/4) + ... 总共是 O(N)
图片以获得更好的说明:
【讨论】:
使用问题的属性。
您不需要对已经排序的数组进行排序。找到slope变化的点,然后使用合适的algorithm得到一个完整的排序数组。
您可以考虑实现一个bitonic sorter,它可以有效地使用此属性。
【讨论】: