Fork me on GitHub

重看算法 -- 递归与分治

递归

典型的斐波那契数列

f(n) = f(n-1) + f(n-2)

 

分治

二分查找

已排好序的数组查找一个数

使用分治的策略

复杂度为O(logn)

 1 #include <iostream>
 2 
 3 using namespace std;
 4 
 5 //在数组a[left...right]中查找元素x
 6 int search(int a[], int x, int left, int right){
 7     int mid;
 8     if (left > right) return -1;//当查找完数组中都没有找到元素时, 返回-1 
 9     mid = (left + right) >> 1;  //整体右移一位,相当于除以2 
10     if (a[mid] == x) return mid;
11     if (a[mid] > x) return search(a, x, left, mid - 1);
12     if (a[mid] < x)return search(a, x, mid + 1, right);
13     
14 } 
15 
16 int main(){
17     int n, x;
18     cin >> n;
19 //    x = n >> 1;
20 //    cout << x; 
21     int a[n];
22     for(int i = 0; i < n; i++)
23         cin >> a[i];
24     
25     cin >> x;
26     cout << search(a, x, 0, n - 1) << endl;
27 }
28 
29 /*
30 9
31 1 2 3 4 5 6 7 8 9
32 5
33 */

 

快速排序

利用互相逼近的方法

 1 #include <iostream>
 2 using namespace std;
 3 
 4 int partition(int a[], int l, int r){
 5     int i = l, j = r + 1;
 6     int x = a[i];
 7     while(true){
 8         while(a[++i] < x && i < r);
 9         while(a[--j] > x);
10         if(i >= j) break;
11         swap(a[i], a[j]);
12     }
13     a[l] = a[j];
14     a[j] = x;
15     return j;    
16 }
17 
18 void quick(int a[], int l, int r){
19     if(l < r){
20         int i = partition(a, l, r);
21         quick(a, l, i - 1);
22         quick(a,i + 1, r);
23     }
24 }
25 int main(){
26     int n;
27     cin >> n;
28     
29     int a[n]; 
30     for(int i = 0; i < n; i++)
31         cin >> a[i];
32     
33     quick(a, 0, n-1);
34     for(int i = 0; i < n; i++)
35         cout << a[i] << " ";
36 } 
37 
38 /*
39 7
40 327 47235 74 5637 28 326 759
41 28
42 74
43 326
44 327
45 759
46 5637
47 47235
48 
49 */

 

寻找第K小的数

与快排思想相似,不过要注意分治之后第k小变成了第几小

 1 #include <iostream>
 2 using namespace std;
 3 
 4 //利用数组的第一个元素将数组划分为两部分,前面都比第一个元素小,
 5 //后面都比第一个元素大,与快速排序划分完全相同
 6 int partition(int a[], int left, int right) {
 7   int i = left + 1;
 8   int j = right;
 9   int x = a[left];
10   while(true) {
11     while (a[i] < x && i < right) i++;
12     while (a[j] > x) j--;
13     if (i >= j) break;
14     swap(a[i], a[j]);
15   }
16   swap(a[left], a[j]);
17   return j;
18 }
19 
20 //在下标从left到right的数组元素中输出第K小的数
21 int find(int num[], int left, int right, int k) {
22     int p = partition(num, left, right); //返回划分元素的下标
23     int n = p - left + 1; // 划分元素为第n小
24     int t;
25     if ( n == k)
26         t = num[p];
27     else if (n < k) //找右半部分的第k-n小
28         t = find(num, p + 1, right, k - n);
29     else //找左半部分的第k小
30         t = find(num, left, p - 1, k);
31 
32     return t;
33 }
34 
35 int main() {
36     int n, k;
37     cin >> n >> k;
38     int num[n];
39     for (int i = 0; i < n; i++)
40         cin >> num[i];
41 
42     cout << find(num, 0, n - 1, k) << endl;
43     return 0;
44 }
45 
46 /*
47 7 5
48 327 47235 74 5637 28 326 759
49 
50 */

 

 

今天先到这吧

posted @ 2021-05-11 15:31  走位,走位  阅读(58)  评论(0)    收藏  举报