反向計算:編寫乙個函式將乙個整型轉換為二進位制形式
反向計算問題,遞迴比迴圈更簡單
分析:需要理解,奇數的二進位制最後一位是1,偶數的二進位制最後一位一定是0,聯想記憶,這個和整型的奇偶性是一致的,1本身就是奇數,0本身是偶數。
十進位制整數轉換為二進位制整數採用"除2取餘,逆序排列"法。
具體做法是:用2整除十進位制整數,可以得到乙個商和餘數,再用2去除商,又會得到乙個商和餘數,如此進行,直到商為0時為止,然後把先得到的餘數作為二進位制數的低位有效位,後得到的餘數作為二進位制數的高位有效位,依次排列起來。
對於數值n,二進位制最後一位=n%2;計算得到的結果是最後要輸出的結果,使用遞迴函式,聯絡遞迴的特點:在遞迴語句之前計算n%2,在遞迴呼叫語句之後輸出結果,這樣先計算的結果反而在最後輸出。
使用了10進製轉2進製的反覆相除,餘數倒置法;
1 #include 2 #include 3當然使用位操作,也能實現這個演算法:void tobinary(unsigned long);4
intmain()
514 system("
pause");
15return0;
16}17//
遞迴函式
18void tobinary(unsigned long
num)
1928
//在遞迴語句之後輸出,這樣就是倒敘輸出
29 printf("%d"
, r);
30 }
//《運算表示把1的二進位制形式整體向左移j位,左移後低位補0,移出的高位部分被捨棄。將無符號十進位制數轉化為標準16位二進位制數
intmain()
else
}cout
<
return0;
}
例如,當j為15時,表示式(1<
位運算的「個性」決定了它直接對資料的二進位制形式進行操作的快捷性(一般計算機的資料儲存基本形式為二進位制形式),兩個相同演算法的程式,用了位運算後會使程式速度上有提高。
使用現成的轉換函式也是可以的
_itoa(120, &buffer, 16); 第乙個引數是要轉換的數,第二個是位址,第三個是進製數
再次看遞迴的優缺點
優點:為一些程式設計問題提供了簡單的辦法,比如上題還有斐貝納契數列問題等,二個數字是1,其餘的每個數字都是前兩個數字的和。這使用遞迴很好。
斐波那契數列問題
問題的由來:13世紀的義大利數學家斐波納契(fibonacci)寫了一本商用的算術和代數手冊<>。在這本書裡,他提出了這麼乙個有趣的問題:
假定一對兔子在它們從出生整整兩個月以後可以生一對小兔子,其後每隔乙個月又可以再生一對小兔子。假定現在在乙個籠子裡有一對剛生下來的小兔子,請問一年以後籠子裡應該有幾對兔子?
讓我們仔細地算一下。
第一、第二個月,小兔子長成大兔子,但還沒成熟不能生小兔子,所以總共只有一對。
第三個月,原有的一對大兔子生了一對小兔子,現在一共有二對了。
第四個月,大兔子又生了一對小兔子,但是第二代的那對小兔子還沒成熟,還不能生小兔子,所以總共有三對。
第五個月,第
一、二兩代的兩對兔子各生了一對小兔子,連同四月份原有的三對,現在一共有五對了。
第六個月,在四月份已經有的三對兔子各生一對小兔了,連同五月份原有的五對兔子,現在一共有八對了。
依此類推,每個月份所有的兔子對數應該等於其上乙個月所有的兔子對數(也就是原有的兔子對數)及其上上個月所有的兔子對數(這些兔子各生了一對小兔子)的總和。
所以每個月的兔子對數應該是1、1、2、3、5、8、13、21、34、55、89、144、233……
每一項都是前兩項之和。因此,一年後籠子裡應該有233對兔子
這些兔子的數目我們稱之為斐波納契數字(fibonacci numbers)。
為方便起見,我們用 fn表示第 n 代兔子的數目。
我們觀察到:
f1=f2=1
而當n≧3時,fn=fn-1+fn-2
最簡單,但是時間複雜度最大的解法是遞迴演算法, 演算法時間複雜度o(n^2)
long注意:c和 c++中所有函式的地位平等,都可以呼叫其他任何函式的同時,被其他任何函式呼叫。比如,main雖然是程式入口函式,但是main也可以遞迴,或者被其他函式呼叫,只不過不經常這樣做。long fibonaccirecursion(unsigned int
n )
else
if (1 ==n)
else
}
下面分析一下這個遞迴解斐波那契數列的過程。以 f(10)為例子,想求 f(10),就要求 f(9)和 f(8),同理,求 f(9),先求 f(8)和 f(7)……使用遞迴樹來表示:
發現這是乙個雙重遞迴,即每次函式對本身進行了兩次呼叫(不是一次呼叫一次,而是每次遞迴對自己呼叫兩次),這樣出現了指數變數階的問題,就是每次遞迴呼叫產生的變數集合是指數階增長的,如遞迴樹所示,很多結點是重複計算的,是浪費的。這樣就很容易程式崩潰。這是乙個典型極端例子,提醒我們要謹慎使用,結合效率。
改進的辦法很自然就是避免重複計算
可以把中間的結果,提前儲存起來,以備後用,下次計算的時候直接使用,無需重複計算。使用迭代遞推的方法。
//演算法時間複雜度o(n),很容易理解,也是很實用的解法。在實際開發中,不會使用第一種遞迴解法,因為效率很低,而第二種方法(也激素迭代),把遞迴用迴圈處理,極大的提高了時間效率。比較常用。遞推的解法,非遞迴
long
long fibonaccirecursion(unsigned int
n )
else
if (1 ==n)
else
return
fn; }
}
一些關於斐波那契的變種
問:乙隻青蛙一次可以跳上一級台階,或者一次跳上兩級台階,求該青蛙跳上乙個n 級的台階總共有多少種跳法?
分析;如果只有一級台階,那麼一共一種跳法,兩級台階,那麼一共兩種跳法,假設有 n 級台階,那麼把跳法記為 f(n),當 n>2的時候,第一次跳的時候有兩種選擇,如果第一次只跳一級,此時跳法數為後面剩下的n-1級台階的跳法數目,也就是為 f(n-1)種,如果第一次跳兩級,此時跳法數目為後面剩下的n-2級台階的跳法數目,也就是 f(n-2),故一共為f(n)=f(n-1)+f(n-2)種,其實就是斐波那契數列。
問:用2x1的小矩形橫放或者豎放去覆蓋更大的矩形,請問用8個2x1的小矩形無重疊的覆蓋乙個2x8的大矩形,一共有多少種方法?
把2x8的覆蓋方法記為 f(8),第乙個1x2的小矩形去覆蓋大矩形最左邊有兩個選擇,豎放或者橫放,當豎著放的時候,右邊還有2x7個小區域,這種情況下的覆蓋方法記為 f(7),如果橫著放,當1x2的小矩形橫著放在左上角的時候,左下角必須也橫著放乙個1x2的小矩形,而在右邊還有2x6的區域,這時的覆蓋方法記為 f(6),因此f(8)=f(7)+f(6),這仍然是斐波那契數列。
dashuai的部落格是終身學習踐行者,大廠程式設計師,且專注於工作經驗、學習筆記的分享和日常吐槽,包括但不限於網際網路行業,附帶分享一些pdf電子書,資料,幫忙內推,歡迎拍磚!
斐波那契數列和反向計算問題
反向計算 編寫乙個函式將乙個整型轉換為二進位制形式 反向計算問題,遞迴比迴圈更簡單 分析 需要理解,奇數的二進位制最後一位是1,偶數的二進位制最後一位一定是0,聯想記憶,這個和整型的奇偶性是一致的,1本身就是奇數,0本身是偶數。十進位制整數轉換為二進位制整數採用 除2取餘,逆序排列 法。具體做法是 ...
斐波那契數列 斐波那契數列python實現
斐波那契數列 fibonacci sequence 又稱 分割數列 因數學家列昂納多 斐波那契 leonardoda fibonacci 以兔子繁殖為例子而引入,故又稱為 兔子數列 指的是這樣乙個數列 1 1 2 3 5 8 13 21 34 在數學上,斐波納契數列以如下被以遞推的方法定義 f 1 ...
迴圈斐波那契數列 斐波那契數列應用
什麼是斐波那契數列 斐波那契數列指的是這樣乙個數列 1,1,2,3,5,8,13,21,34,55,89,144 這個數列從第3項開始,每一項都等於前兩項之和 台階問題 有一段樓梯有10級台階,規定每一步只能跨一級或兩級,要登上第10級台階有幾種不同的走法?這就是乙個斐波那契數列 登上第一級台階有一...