日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

经典基础算法之面试题(系列一)(转)

發布時間:2023/12/18 编程问答 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 经典基础算法之面试题(系列一)(转) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

1. 打靶問題的遞歸解法

Technorati 標記:?遞歸算法,字典法,二分法,打靶問題,日期問題,求冪,多項式求值

倫敦奧運會火熱進行中,讓我們來看個打靶的問題:一個射擊運動員打靶,靶一共有10環,求連開10槍打中90環的可能行有多少種?
分析:這是一個典型遞歸求解問題。假設第10槍打x環,則將問題轉換為剩下9槍打90-x環的可能有多少種,x的取值范圍為[0, 10],根據加法原理,則:10槍打90環的可能 = 第10槍打0環,剩下9槍打90環的可能 + 第10槍打1環,剩下9槍打89環的可能 + 第10槍打2環,剩下9槍打88環的可能?
+ 第10槍打3環,剩下9槍打87環的可能 + 第10槍打4環,剩下9槍打86環的可能 + 第10槍打5環,剩下9槍打85環的可能?
+ 第10槍打6環,剩下9槍打84環的可能 + 第10槍打7環,剩下9槍打83環的可能 + 第10槍打8環,剩下9槍打82環的可能
+ 第10槍打9環,剩下9槍打81環的可能 + 第10槍打10環,剩下9槍打80環的可能。

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?

遞歸的停止條件為:
1. 若環數小于0 或者 剩下的環數大于剩下的槍數乘以10(即剩下每槍打10環用不玩所剩環數),則該遞歸路徑不記入可能情況。
2. 若不滿足條件1,且所剩槍數為1,則該遞歸路徑記為1中可能情況。

1: #include <stdio.h>2: 3: int recursion(int count, int score)4: {5: if (score < 0 || score > count * 10) {6: return 0;7: }8: 9: if (1 == count) { 10: return 1; 11: } 12: 13: int i = 0; 14: int sum = 0; 15: 16: for (; i <= 10; ++i) { 17: sum += recursion(count - 1, score - i); 18: } 19: 20: return sum; 21: } 22: 23: int main() 24: { 25: printf("result: %d\n", recursion(10, 90)); 26: return 0; 27: }

2. 求多項式的值與求冪的快速算法

2.1 求多項式的值

已知多項式中的系數a0,a1,a2……an及x的值,求f(x)。

多項式求值問題可以利用輾轉相乘的方式進行計算,根據上面的式子分析,可以將上式轉換為: f(x) = ((((an * x) + an-1) * x + an-2) * x? ……. + a1) * x + a0?
有了這個變形,代碼自然而然就能寫出來了:

1: #include <stdio.h>2: 3: int polynomial(const int *coefficient, int n, int x)4: {5: int sum = 0;6: 7: int i = n - 1;8: for (; i != 0; --i) {9: sum = sum * x + coefficient[i]; 10: } 11: 12: return sum * x + coefficient[0]; 13: } 14: 15: int main() 16: { 17: int coeff[5] = {1, 2, 3, 4, 5}; 18: printf("result: %d\n", polynomial(coeff, sizeof(coeff) / sizeof(coeff[0]), 10)); 19: return 0; 20: }

2.2 求冪的快速算法

求x的p次冪本是簡單的問題,可以將x次乘p次就可以了,這里我們當然不是要討論這種計算方法,這里討論的是怎樣高效計算。
有沒有可能減少做乘法的次數呢?讓我們來做一個分析,考慮x的6次冪的情況:x * x * x * x * x * x = (x * x * x) * (x * x * x)
等式前面部分需進行6次乘法,后半部分需計算(x * x * x) ,然后乘以上次計算的值即可,共4次乘法。
通過上述分析可知,求x的p次冪可以通過遞歸折半的方法來減少乘法的次數,循著這個思考,實現就不太困難了。

1: #include <stdio.h>2: 3: /* 統計乘法的次數 */4: static int multiply_count = 0;5: 6: /* 求x的p次冪 */7: int power(int x, int p)8: {9: int ret = 0; 10: 11: if (1 == p) { 12: return x; 13: } 14: 15: /* 先計算x的p/2次冪 */ 16: ret = power(x, p >> 1); 17: ret *= ret; 18: ++multiply_count; 19: 20: /* 若p是奇數,則再乘一次x */ 21: if (0 != p % 2 /* 求模本身是一個耗性能的運算,這里可優化為 p – ((p >> 1) << 1) */) { 22: ret *= x; 23: ++multiply_count; 24: } 25: 26: return ret; 27: } 28: 29: int main() 30: { 31: printf("resulut: %d\n", power(2, 20)); 32: printf("multiply count: %d\n", multiply_count); 33: return 0; 34: }

計算2的20次冪總共進行5次乘法就足夠了,而原始的算法需要20次,那么這種算法究竟需要多少次乘法呢?
由于該算法根本思想是折半遞歸,類似于2分查找,所以乘法的次數為lgp取天花板值這個數量級的(lgp表示以2為底p的對數)。
整型int最多表示2的32次冪,因此最多節省24次乘法,對于現代的計算機,這似乎不是特別重要,但是在以下情況下該算法具有重要價值:
1. 對于需要高頻率計算冪的情況;
2. 對于大數高精度計算的情況,如需計算2的10000次冪。
當然了,這也是對遞歸算法和2分法的巧妙應用,學習其思想吧。

3. 一年中的第n天是幾月幾號?

和這個問題類似的問題還有:
1. 給定某年某月某日,問這是這年的第多少天?
2. 已知某年的1月1號是星期幾,求給定的某年某月某日是星期幾?

其實這類問題的共同點在于它們都需要考慮閏年問題,大月小月問題;
首先我們解決閏年問題,根據閏年的定義定義如下宏來判斷某年是否是閏年:
#define IS_LEAP(X) (((X) % 400 == 0 || (X) % 100 != 0 && (X) % 4 == 0) ? 1 : 0)

在來看大月小月問題,可以定義如下二維數組,用day_count_of_month[0][12]表示潤年情況下每月的天數,用day_count_of_month[1][12]表示非潤年情況下每月的天數(這就是傳說中的字典法了,就是根據提供的信息查表,類似于查字典,所以叫做字典法):
int day_count_of_month[2][12] = {

??????????????????????????????????????????????? {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},?
??????????????????????????????????????????????? {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}

?????????????????????????????????????????????? };

1: #include <stdio.h> 2: 3: #define IS_LEAP(X) (((X) % 400 == 0 || (X) % 100 != 0 && (X) % 4 == 0) ? 1 : 0)4: int day_count_of_month[2][12] = {{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, 5: {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31} }; 6: /* 計算year年的第n天是幾月幾號 */7: void convert_to_date(int year, int n) 8: { 9: int leap = IS_LEAP(year); 10: if(year < 1970 || year > 5000 || n <= 0 || n > 365 + leap) { 11: printf("bad year\n"); 12: } 13: 14: int i = 0; 15: for(; n > day_count_of_month[leap][i]; ++i) { 16: n -= day_count_of_month[leap][i]; 17: } 18: 19: printf("year : %d, month : %d, day : %d\n", year, i + 1, n); 20: } 21: 22: int main() 23: { 24: convert_to_date(2012, 230); 25: }

上面這段代碼解決了第一個問題,第二個問題可以轉換為類似第一個問題的問題:
先計算給定的某年某月某日到給定已知這天的總天數s=>s%7=>利用模運算結果來推算所求日期的星期情況即可。

?

http://www.cnblogs.com/dskit/archive/2012/08/11/2633736.html

?

轉載于:https://www.cnblogs.com/bizhu/archive/2012/08/19/2646325.html

總結

以上是生活随笔為你收集整理的经典基础算法之面试题(系列一)(转)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。