如何输出B的排列使得A是一个摇摆不定的?

时间:2015-02-17 17:24:43

标签: arrays algorithm sorting

我遇到了以下问题:

  

给定实数的未排序数组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)时间内完成。

我应该使用计数排序/基数排序/桶排序来获得线性时间然后改变它以获得一个摇摆不定的数组吗?

2 个答案:

答案 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])

正确性证明:

让我们使用归纳法:

  1. 基本情况:只处理一个元素,不违反任何约束。

  2. 步骤:如果i % 2 == 0:如果我们在此步骤中没有交换任何内容,则前缀仍然有效。否则,我们会遇到以下情况:a[i - 2] >= a[i - 1] > a[i]。当我们进行交换时,我们可以看到i - 2i - 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;
}