有乙個長度為2n的陣列,希望排序後變成。
書上講了先用完美洗牌演算法將陣列排序為,然後再兩兩交換,就變為題目所要求的那樣。
書上完美洗牌演算法講得很好,我這裡就簡單記錄下。
注意,陣列下標是從1開始儲存要求排序的資料。
首先,對於將排序為,通過觀察可以發現這樣乙個事實:任意的第i個元素都最終換到了(2i)%(2n+1)的位置。即
第1個->第2個,
第2個->第4個,
第3個->第6個,
第4個->第8個,
第5個->第1個,
第6個->第3個,
第7個->第5個,
第8個->第7個。
並且還有這樣乙個事實,讓原始序列中的每乙個元素置換到最終序列裡的位置時,形成了兩個圈:乙個是1->2->4->8->7->5->1,另乙個是3->6->3。因此,只要知道圈裡最小位置編號的元素(即圈的頭部),順著圈走一遍就可以達到目的。
有大神得出了這樣乙個結論:若2n=3^k-1,則可確定圈的個數及各自頭部的位置,即恰好只有k個圈,且每個圈頭部的起始位置分別是1,3,9,…,3^(k-1)。
所以對於給定的任意n,可將整個陣列一分為二,讓一部分的長度滿足上述結論,剩下的n-m部分單獨計算。
也就是如下所示,數字指的都是下標:
1,…,m,m+1,…,n,n+1,…,n+m,n+m+1,…,2n
且為了能讓前部分的序列滿足結論2m=3^k-1,可以把中間兩段長度為n-m和m的段交換位置,即相當於把m+1,…,n,n+1,…,n+m的段迴圈右移m次,這樣操作後,陣列的前部分的長度為2m,這部分就恰好有k個圈。
最後的完整流程就是:
輸入:陣列a[1,2,…,2n]。
第1步:找到2m=3^k-1,使得3^k <= 2n <= 3^(k+1)。
第2步:把陣列中的a[m+1,…,n+m]那部分迴圈右移m位。
第3步:因對於2m長度的陣列,剛好有k個圈,且每個圈的頭部為3^i,其中i=0,1,2,…,k-1,所以對每個圏執行走環演算法cycleleader,且因陣列長度為m,所以需要對2m+1取模。
第4步:對陣列的後面部分a[2m+1,…,2n]繼續使用本演算法,這相當於n減少了m。
//
// created by huxijie on 17-3-18.
// 完美洗牌演算法
#include
using
namespace
std;
//注意,陣列從下標1處開始存資料
//翻轉陣列
void reverse(int
array,int from,int to)
}//迴圈右移m位
void rightshifting(int
array,int n,int m)
//走環演算法:i->2i mod (2n+1)
//陣列下標從1開始,from是圈的頭部,mod是要取模的數,因此mod應該為2n+1
void cycleleader(int
array,int from,int mod)
}int *perfectshuffle(int
array,int n)
m /= 2;
//第2步
rightshifting(array + m, n, m);
//第3步
for (i = 0, t = 1; i < k; ++i, t *= 3)
//第4步
array += 2 * m;
n -= m;
}//n=1時
t = array[1];
array[1] = array[2];
array[2] = t;
return start;
}int *shuffle(int
array,int n)
return result;
}int main()
int *result = shuffle(array, n);
for (int i = 1; i < 2 * n + 1; ++i)
cout
0;}
162
7384
9510process finished with
exit code 0
完美洗牌演算法
原文 完美洗牌問題 給定乙個陣列a1,a2,a3,an,b1,b2,b3.bn,把它最終設定為b1,a1,b2,a2,bn,an這樣的。分析 首先,有的問題要求把它換成a1,b1,a2,b2,an,bn。其實也差不多。我們可以 迴圈n次交換a1,b1,a2,b2,把陣列變為b1,b2.bn,a1,a...
完美洗牌演算法
沒把空間複雜度o 1 的搬過來 問題描述 有乙個長度為2n的陣列,希望排序後變成,請考慮有沒有時間複雜度為o n 而空間複雜度為o 1 的解法。string a string temp new string len for int i 1 i len i temp 2 i len a i 經過上面處...
完美洗牌演算法
完美洗牌就是將一副牌平均分成兩份 26張 來交錯洗牌,如此迴圈反覆一定次數後,又變回洗牌前的順序了。即 a 1,a 2.a n,b 1,b 2.b n的序列變為b 1,a 1,b 2,a 2.b n,a n 我知道這 很shi,只是拋磚,向各位高人請教更好的演算法,謝謝 完美洗牌就是將一副牌平均分成...