1.在排序數組中,找出某整數出現的次數
問題定義:給定一個整數數組arr,數組中元素的個數是n,數組arr已經排好序,要在arr中找到某個某個整數x出現的次數,比如arr[] = {1,2,2,3,5,10},找到2的出現次數就是2。
問題分析:相必看到有序數組的字樣,想到利用二分應該是很順利成章的事了。我們可以利用二分搜索求出x在arr中出現的第一個位置lo和最后一個位置hi,然后計算hi-lo+1的值就是x在arr出現的次數了,當然也有可能x並沒有在arr中出現過,這時hi和lo都等於-1。時間復雜度是兩個二分的復雜度:2*O(log n)。看看代碼是怎么實現的吧!!
相關代碼:

1 #include <iostream> 2 3 using namespace std; 4 5 //求上屆,返回值是-1表示在arr中沒找到x 6 int upper_bound(int *arr,int n,int x) 7 { 8 bool flag = false;//用於判斷x是否存在於arr中 9 int lo,hi,mid; 10 lo = 0 ; hi = n-1; 11 while(lo <= hi) 12 { 13 if(hi - lo == 0) 14 { 15 if(arr[lo] == x) 16 { 17 flag = true; 18 } 19 break; 20 } 21 mid = (lo + hi + 1) / 2;//求上界要保證能取到最大值 22 if(arr[mid] <= x) 23 { 24 if(arr[mid] == x)//x在arr中出現過 25 flag = true; 26 lo = mid; 27 } 28 else 29 { 30 hi = mid - 1; 31 } 32 } 33 if(flag) 34 return lo; 35 return -1; 36 } 37 38 //求下界,返回值是-1表示在arr中沒找到x 39 int lower_bound(int *arr,int n,int x) 40 { 41 bool flag = false;//用於判斷x是否存在於arr中 42 int lo,hi,mid; 43 lo = 0 ; hi = n-1; 44 while(lo <= hi) 45 { 46 if(hi - lo == 0) 47 { 48 if(arr[lo] == x) 49 { 50 flag = true; 51 } 52 break; 53 } 54 mid = (lo + hi) / 2; 55 if(arr[mid] >= x) 56 { 57 if(arr[mid] == x) 58 flag = true; 59 hi = mid; 60 } 61 else 62 { 63 lo = mid + 1; 64 } 65 } 66 if(flag) 67 return lo; 68 return -1; 69 } 70 //計算x在arr中的出現次數 71 void count(int *arr,int n,int x) 72 { 73 int hi = upper_bound(arr,n,x); 74 int lo = lower_bound(arr,n,x); 75 if(hi != -1) 76 { 77 cout<<x<<" 在數組中出現了 "<<hi - lo +1 <<" 次 !!"<<endl; 78 } 79 else 80 { 81 cout<<x<<" 在數組中出現了 0 次 !!"<<endl; 82 } 83 } 84 int main() 85 { 86 int arr1[] = {1,2,2,3,5,6}; 87 count(arr1,6,4); 88 count(arr1,6,2); 89 90 cout<<endl; 91 int arr2[] = {0,1}; 92 count(arr2,2,0); 93 94 cout<<endl; 95 int arr3[] = {1}; 96 count(arr3,1,1); 97 return 0; 98 }
小結:有人也提到了這樣解法,即:先利用二分找到x在arr中出現的第一個位置lo,然后從lo下一位置開始向后直到下標達到n-1或者找到不等於x的情況結束,每前進一步,x出現的次數加 1,這樣也能求出x在arr中出現的次數,但是不要忘了這種情況,即arr = {1,1,1,1,1,1},然后x = 1,那么這時利用這種方法的時間復雜度就是O(n+log n) 了。也就是說在最壞的情況下,時間復雜度太高。
2.去掉字符串中多余的空格
問題描述:給定一個字符串數組,要求去掉首部和尾部的所有空格,字符串中間的空格出現1次以上只保留一個空格,比如str[] = “ Wo shi Vincent ”,經過處理后應為“Wo shi Vincent”。
問題分析:這是一個簡單的字符串處理的問題,顯然開頭、結尾、和中間的空格處理方式是不一樣的,我的思路是遍歷一遍字符數組,首先處理開頭的空格,方法是:全部刪除;然后是字符串中間的空格,方法是:遇到空格,值保留第一個空格;遍歷結束后,新串的最后一個字符是空格,就代表是原字符串尾部有空格存在,所以要去掉。如此一來就完事了,值需要遍歷一遍,時間復雜度是O(n)。
相關代碼:

1 #include <iostream> 2 #include <cstring> 3 4 using namespace std; 5 6 void remove_extra_space(char *str) 7 { 8 int Start = 0 , End = strlen(str); 9 int NewStart = 0; 10 while(Start < End) 11 { 12 //去掉開頭的空格 13 if(Start == 0) 14 { 15 while(Start < End && str[Start] == ' ') 16 { 17 Start++; 18 } 19 } 20 //處理中間的空格,多個空格值保存一個 21 if(str[Start] == ' ') 22 { 23 str[NewStart++] = str[Start++]; 24 while(Start < End && str[Start] == ' ') 25 { 26 Start++; 27 } 28 } 29 //復制非空格的字符 30 else 31 { 32 str[NewStart++] = str[Start++]; 33 } 34 } 35 //去掉末尾的空格 36 if(str[NewStart-1] == ' ') 37 { 38 str[NewStart-1] = '\0'; 39 } 40 } 41 42 int main() 43 { 44 char str[] = " wo shi Vincent "; 45 remove_extra_space(str); 46 cout<<str<<"@@@@@@"<<endl; 47 return 0; 48 }
3.求1024!的結果中末尾有多少個0
問題分析:首先1024!呀,是多么大的一個數呢??想求出來結果然后在看末尾有多少0是不現實的,我們可以分析要求的是:末尾有多少個0。那么的0的個數有什么決定的呢?10 = 2 * 5 ,顯然一對(2 , 5)就能湊出一個末尾0,也就是說末尾0的個數是由因子2和5的個數決定的,更確切的說是由因子的個數決定的(考慮一下為什么吧!?),那么1~1024這1024個數中包含多少個因子5呢?顯然這1024個數有的包含1個因子5,有的包含兩個因子5(5^2 = 25),有得包含三個因子5(5^3 = 125),有的包含4的因子5(5^4 = 625)。那么一共包含多少因子5呢?
包含一個因子5的數有 1024 / 5 = 204 個。
包含兩個因子5的數有 1024 / 25 = 40 個。
包含三個因子5的數有 1024 / 125 = 8 個。
包含四個因子5的數有 1024 / 625 = 1 個。
也就是說1~1024這1024個數一共包含因子5的個數是: sum = 204 + 40 + 8 + 1 個。
小結:注意類似的問題可以借鑒這個題的解題思路~~~~~~
4.給定能隨機生成整數1到5的函數,寫出能隨機生成整數1到7的函數
問題分析:現在給了一個能隨機生成1~5的隨機函數,怎樣利用這個已知條件生成一個1~7的隨機函數呢?既然要生成的是隨機數那么生成1,2,3,4,5,6,7的概率就應該是一樣的。顯然現在光生成1~5之間的數就不夠了,我們想到應該要加大生成數的范圍,並且加大范圍的同時還要保證每個數產生的概率一樣,於是有這樣一種方法用這個表達式來擴大生成數范圍:rand5()*5+rand5(),新的數據范圍變成:6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30.並且可以看出來這個25個數出現的可能性是一樣的,於是我們可以只用6~26之間的21個數變成1~7這7個數,於是就是要每3個數對應一個數,即:
6,7,8對應1
9,10,11對應2
…………
24,25,26對應7
這種變化對應的方式是(6 - 3)/ 3 = 1,(7 - 3) / 3 = 1,(8-3) / 3 = 1.看看代碼吧:
相關代碼:

1 int rand7() 2 { 3 int i; 4 //直到產生6~26之間的數跳出循環 5 while((i=rand5()*5+rand5()) > 26) ; 6 return (i-3)/3; 7 }
學習中的一點總結,歡迎拍磚哦^^