《算法導論》學習記錄目錄html
一、寫出一個運行時間爲的算法,使之能在給定一個由n個整數構成的集合S和另外一個整數時,判斷出S中是否存在有兩個其和等於x的元素。算法
首先對集合進行排序,用歸併排序(),而後再從集合的第一個元素到最後一個元素,對集合進行二分查找,查找x減去該元素()數組
1 #include <stdio.h> 2 #include <stdlib.h> 3 4 void merge(int A[], int p, int q, int r){ 5 int n1 = q - p + 1; 6 int n2 = r - q; 7 int i, j, k; 8 int *L = malloc(n1 * sizeof(int)); 9 int *R = malloc(n2 * sizeof(int)); 10 11 for(i = 0; i < n1; i++) 12 L[i] = A[p+i]; 13 for(j = 0; j < n2; j++) 14 R[j] = A[q+j+1]; 15 16 i = 0; 17 j = 0; 18 for(k = p; k <= r; k++){ 19 if(i < n1 && j < n2){ 20 if(L[i] <= R[j]){ 21 A[k] = L[i]; 22 i++; 23 } 24 else{ 25 A[k] = R[j]; 26 j++; 27 } 28 } 29 else if(i >= n1){ 30 A[k] = R[j]; 31 j++; 32 } 33 else if(j >= n2){ 34 A[k] = L[i]; 35 i++; 36 } 37 } 38 } 39 40 /*歸併排序*/ 41 void merge_sort(int A[], int p, int r){ 42 if(p < r){ 43 int q = (p + r) / 2; 44 merge_sort(A, p, q); 45 merge_sort(A, q+1, r); 46 merge(A, p, q, r); 47 } 48 } 49 50 /*二分查找*/ 51 int binary_search(int A[], int length, int key) { 52 int p = 0; 53 int q = length -1; 54 int m; 55 while(p < q){ 56 m = (p + q) / 2; 57 if(A[m] > key) 58 q = m; 59 else 60 p = m + 1; 61 } 62 if(A[p] == key) 63 return p; 64 else 65 return -1; 66 } 67 68 /*檢查集合中是否存在兩個數之和爲x*/ 69 int check_sum(int A[], int length, int sum) { 70 int i; 71 int x, y; 72 for(i = 0; i < length; i++){ 73 x = A[i]; 74 y = sum - x; 75 if(binary_search(A, length, y)) 76 return 1; 77 else 78 return -1; 79 } 80 } 81 82 int main() { 83 int num; 84 int i; 85 int sum; 86 printf("Input the number: "); 87 scanf("%d", &num); 88 int *arry = malloc( num * sizeof(int)); 89 90 for(i = 0; i < num; i++) 91 scanf("%d", &arry[i]); 92 merge_sort(arry, 0, num - 1); //進行排序 93 94 printf("Input the sum: "); 95 scanf("%d", &sum); 96 int flag = check_sum(arry, num, sum); 97 if(flag) 98 printf("Yes!\n"); 99 else 100 printf("No!\n"); 101 return 0; 102 }
二、關於分治策略:將原問題劃分紅爲n個規模較小而結構與原問題類似的子問題,遞歸地解決這些子問題,而後再合併其結果,獲得原問題的解。學習
給出一個算法,它能用的最壞狀況運行時間,肯定n個元素的任何排列中的逆序對的數目。(提示:修改合併排序)spa
算導的提示是修改合併排序(歸併排序),經過將數組分紅小數組,先對小數組進行統計逆序對數目(左右兩個將要合併的數組,若是右面的數組的第一個值比左面的小,就有逆序對。PS:小數組的順序已經排好,因此逆序對的數目爲左邊數組的長度減去左邊數組的第一個值的下標),而後合併兩個小數組,接着繼續合併數組知道還原爲原來的數組長度。3d
1 #include <stdio.h> 2 #include <stdlib.h> 3 4 int merge_inversion(int A[], int p, int q, int r){ 5 int n1 = q - p + 1; 6 int n2 = r - q; 7 int i, j, k; 8 int inversion = 0; 9 int *L = malloc(n1 * sizeof(int)); 10 int *R = malloc(n2 * sizeof(int)); 11 12 for(i = 0; i < n1; i++) 13 L[i] = A[p+i]; 14 15 for(j = 0; j < n2; j++) 16 R[j] = A[q+j+1]; 17 18 i = 0; 19 j = 0; 20 for(k = p; k <= r; k++){ 21 if(i < n1 && j < n2){ 22 if(R[j] < L[i]){ 23 inversion = inversion + (n1 -1) - i + 1; 24 A[k] = R[j]; 25 j++; 26 } 27 else{ 28 A[k] = L[i]; 29 i++; 30 } 31 } 32 else if(i >= n1){ 33 A[k] = R[j]; 34 j++; 35 } 36 else if(j >= n2){ 37 A[k] = L[i]; 38 i++; 39 } 40 } 41 return inversion; 42 } 43 44 int count_inversion(int A[], int p, int r){ 45 int inversion = 0; 46 if(p < r){ 47 int q = (p + r) / 2; 48 inversion += count_inversion(A, p, q); 49 inversion += count_inversion(A, q+1, r); 50 inversion += merge_inversion(A, p, q, r); 51 } 52 return inversion; 53 } 54 55 int main(){ 56 int num; 57 int i; 58 int sum; 59 printf("Input the number: "); 60 scanf("%d", &num); 61 int *arry = malloc( num * sizeof(int)); 62 63 for(i = 0; i < num; i++) 64 scanf("%d", &arry[i]); 65 66 int count = count_inversion(arry, 0, num-1); 67 68 printf("The number of inversion is : %d\n", count); 69 70 return 0; 71 }