分治

分治与贪心

分治 贪心策略
step1 分:问题分解 问题分解为多个子问题
step2 治:逐个击破 子问题求局部最优解
step3 合:合并求解 局部最优解进行组合

对于分治,问题分解之后可能还需要继续分解。对于贪心策略,子问题将无需继续分解。

实列

快速排序算法就用到了分治策略

求解Fibonacci数列

方法 时间复杂度
分治法 O(2n)
递推法 O(n)
矩阵快速幂 O(logn)

分治法

#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<math.h>
using namespace std;

int Fibonacci(int n){
    if(n == 0 || n == 1){
        return n;
    }
    else{
        return Fibonacci(n-1) + Fibonacci(n-2);
    }
}

int main(){
    int n;
    while(scanf("%d", &n) != EOF){
        printf("%d\n", Fibonacci(n));
    }
    return 0;
}

递推法

分治法存在大量的重复计算,因此效率低下,解决方法:存储中间值

#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<math.h>
using namespace std;

const int MAXSIZE = 35;
int fibonacci[MAXSIZE];

void Initial(){
    fibonacci[0] = 0;
    fibonacci[1] = 1;
    for(int i = 2; i <= MAXSIZE; ++i){
        fibonacci[i] = fibonacci[i-1] + fibonacci[i-2];
    }
    return ;
}

int main(){
    int n;
    Initial();
    while(scanf("%d", &n) != EOF){
        printf("%d\n", fibonacci[n]);
    }
    return 0;
}

矩阵快速幂法

分治

上面公式可用数学归纳法证明

#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<math.h>
using namespace std;

const int MAXSIZE = 110; 

struct Matrix{
    int data[MAXSIZE][MAXSIZE];
    int row, col;
    Matrix(int r, int c): row(r), col(c) {}
};

Matrix Mul(Matrix a, Matrix b){
    Matrix answer = Matrix(a.row, b.col);
    for(int i = 0; i < answer.row; ++i){
        for(int j = 0; j < answer.col; ++j){
            answer.data[i][j] = 0;
            for(int k = 0; k < a.col; ++k){
                answer.data[i][j] += a.data[i][k] * b.data[k][j];
            }
        }
    }
    return answer;
}

Matrix QuickPowerMatrix(Matrix x, int n){
    Matrix answer = Matrix(x.row, x.col);
    //初始化单位矩阵
    for(int i = 0; i < answer.row; ++i){
        for(int j = 0; j < answer.col; ++j){
            if(i == j){
                answer.data[i][j] = 1;
            }
            else{
                answer.data[i][j] = 0;
            }            
        }
    }

    while(n){
        if(n % 2){
            answer = Mul(answer, x);
        }
        n /= 2;
        x = Mul(x, x);
    }
    return answer;
}

int main(){
    int n;
    while(scanf("%d", &n) != EOF){
        Matrix fibonacci = Matrix(2, 2);
        fibonacci.data[0][0] = 1;
        fibonacci.data[0][1] = 1;
        fibonacci.data[1][0] = 1;
        fibonacci.data[1][1] = 0;
        Matrix answer = QuickPowerMatrix(fibonacci, n);
        printf("%d\n", answer.data[0][1]);
    }
    return 0;
}
上一篇:Clark变换等幅值与等功率系数计算


下一篇:剑指 Offer 40. 最小的k个数