我遇到了以下问题:
给定实数的未排序数组
B[1 . . 2n+1]
,给出线性 时间算法输出A[1..2n+1]
的{{1}}这样的排列B
A
是一个摇摆不定的人。
我基本上做了合并排序并对其进行了改动:
MergeSort(a,n)
int i=2;
while (i ≤ n)
{
Swap(a[i−1], a[i]);
i=i+2;
}
但时间复杂度为O(nlogn) + O(n)
(分别来自排序和循环),产生O(nlogn)
。但我希望在O(n)
时间内完成。
我应该使用计数排序/基数排序/桶排序来获得线性时间然后改变它以获得一个摇摆不定的数组吗?
答案 0 :(得分:8)
有一个简单的线性解决方案:
for i = 2 ... 2 * n - 1:
if i % 2 == 0 and a[i] < a[i - 1] or i % 2 == 1 and a[i] > a[i - 1]:
swap(a[i], a[i - 1])
正确性证明:
让我们使用归纳法:
基本情况:只处理一个元素,不违反任何约束。
步骤:如果i % 2 == 0
:如果我们在此步骤中没有交换任何内容,则前缀仍然有效。否则,我们会遇到以下情况:a[i - 2] >= a[i - 1] > a[i]
。当我们进行交换时,我们可以看到i - 2
和i - 1
元素没有违反约束,并且最后一个位置是固定的。对于奇数i
,情况类似。
答案 1 :(得分:-1)
以下是上述算法的C ++实现。
#include <iostream>
using namespace std;
void swap(int& a,int& b){
a=a+b;
b=a-b;
a=a-b;
}
int main() {
int*B ;
int n;
cin>>n ; n=2*n;
B=new int[n] ;
for(int i=0;i<n;i++){
cin>>B[i] ;
}
for(int i=1;i<n;i++){
if(i%2==0&&B[i]>B[i-1])
swap(B[i],B[i-1]);
else if(i%2==1&&B[i]<B[i-1])
swap(B[i],B[i-1]);
}
for(int i=0;i<n;i++){
cout<<B[i]<<" ";
}
return 0;
}