題目要求對長為n的bit陣列輸出所有0、1組合,相鄰兩個只有乙個bit發生變化。如果n=2,則可以有下面的輸出:
0000
0101 11
10 10
11
那麼左邊的是正確的,右邊的不正確,因為01和10之間差了兩位。
首先想到的辦法是如下遞迴,設f(n)返回乙個長度為n的bit陣列,並且陣列按照題目要求的那樣排列。那麼f(n+1)可以如下獲得:
f(n+1)= 連線
由於f(n)的元素滿足要求,其倒排肯定也滿足要求。唯一要證明的是接頭的地方是否滿足要求。容易看到f(n)的最後乙個元素必然等於f(n)倒排的第乙個元素,因此連線處也是滿足要求的。
演算法如下:
這個演算法有個缺點是需要生成很多臨時陣列,並且最後需要乙個長度為2的n次方的大陣列來儲存結果。能不能找到一組就立刻輸出,不儲存呢?回到最初的遞迴表示式:
f(n)= 並上
可以得到如下樹結構:
注意到第三層的11和10是倒過來的,按照原始演算法下先是10再是11。由此我們想到有兩種遞迴:
f(n)= 並上 先0後1
f(n)= 並上 先1後0
需要結合起來,因此有如下的表示式:
f(n,bitflag)= 並上
那麼x是0還是1呢,bitflag』又該怎麼變化呢?
顯然bitflag為0的時候表示正常,為1表示需要翻轉。正常情況先0後1,翻轉情況先1後0.
那什麼時候需要翻轉?注意到如果父節點包含奇數個1則需要翻轉。因為演算法保證f(n-1)的序列滿足相鄰數隻差乙個bit的需求,那麼要想它的下一層是相連線的,必須要求相鄰的兩個子樹是映象。也就是說如果i子樹翻轉了,i+1就不能翻轉。00顯然不翻轉,故01翻轉,11不翻轉,10翻轉。
因此演算法表示式為:
f(n,bitflag)= 並上 bitflag==0**如下,if bit0那個可以壓縮。但是為了方便理解,就不壓縮了:f(n,bitflag)= 並上 bitflag==1
line=0;
def changeonebit1(a, n, bit0):
global line;
if(n==0):
line=line+1
print str(line)+':'+str(a);
else:
if(bit0==0):
a[n-1]=0;
changeonebit1(a,n-1,bit0 ^ a[n-1]);
a[n-1]=1;
changeonebit1(a,n-1,bit0 ^ a[n-1]);
else:
a[n-1]=1;
changeonebit1(a,n-1,bit0 ^ a[n-1]);
a[n-1]=0;
changeonebit1(a,n-1,bit0 ^ a[n-1]);
執行結果如下:
1:[0, 0, 0, 0]
2:[1, 0, 0, 0]
3:[1, 1, 0, 0]
4:[0, 1, 0, 0]
5:[0, 1, 1, 0]
6:[1, 1, 1, 0]
7:[1, 0, 1, 0]
8:[0, 0, 1, 0]
9:[0, 0, 1, 1]
10:[1, 0, 1, 1]
11:[1, 1, 1, 1]
12:[0, 1, 1, 1]
13:[0, 1, 0, 1]
14:[1, 1, 0, 1]
15:[1, 0, 0, 1]
16:[0, 0, 0, 1]
總結一下,這個題目其實只是資料排列的乙個小小的變化,但是需要透徹的理解遞迴的本質,寫出遞迴表示式,並進一步描繪遞迴空間樹,找出節點的規律,才能進一步實現演算法。 technorati tags: 演算法,遞迴
一位原碼的乘法規則 原碼一位乘法的實現演算法
原碼一位乘法的實現演算法 一 用原碼實現乘法運算是十分方便的。原碼表示的兩個數相乘,其乘積的符號為相乘兩數符號的異或值,數值則為兩數絕對值之積。假定 x 原 xsx1 x2 xn y 原 ysy1y2 yn 則 x y 原 x 原 y 原 xs ys x1x2 xn y1 y2 yn 結果是把符號位...
群裡一位老大貼的排序演算法
這是我qq群裡乙個老大的貼的排序演算法,感覺比較經典,所以就貼到這了.void swap int a,int b void sort int arr,int beg,int end swap arr l arr beg sort arr,beg,l sort arr,r,end void sort2...
mysql在表的某一位置增加一列的命令
如果想在乙個已經建好的表中新增一列,可以用諸如 alter table t1 add column addr varchar 20 not null 這條語句會向已有的表t1中加入一列addr,這一列在表的最後一列位置。如果我們希望新增在指定的一列,可以用 alter table t1 add co...