MIT算法导论-第三讲-分治

分治法思想

(1)Divide,把问题分解成子问题。

(2)Conquer,递归地解决子问题。

(3)Combine,合并子问题的解得到原问题的解。


1.归并排序

Step1:Devide——将待排序的序列分成两个子序列

Step2:Conquer——(递归地)对每个子序列进行排序

Step3:Combine——将排序好的子序列合并

T(n)=2*T(n/2)+O(n)=Θ(nlogn)

代码如下:

//合并已有序的a[p,...,q]数组和a[q+1,...,r]数组
void Merge(int a[],int p,int q,int r) {

    //len1=a[p,...,q]数组长度;len2=a[q+1,...,r]数组长度
    int len1 = q-p+1;
    int len2 = r-q;

    //为a[p,...,q],a[q+1,...,r]的临时数组L,R赋值
    int L[len1],R[len2];
    for(int i = 0;i<len1;i++)
        L[i] = a[p+i];
    for(int j =0;j<len2;j++)
        R[j] = a[q+j+1];

    int i=0,j=0,k=0;
    //比较L,R两个待合并数组的值,将较小的值插入原数组中
    //直到L或R数组访问完最后一个元素
    while(i<len1 && j<len2) {
        if(L[i]<R[j]) {
            a[p+k]=L[i];
            i++;
        }
        else {
            a[p+k]=R[j];
            j++;
        }
        k++;
    }
    //如果L数组没到达尾部
    while(i<len1) {
        a[p+k] = L[i];
        i++;
        k++;
    }
    //如果R数组没到达尾部
    while(j<len2) {
        a[p+k] = R[j];
        j++;
        k++;
    }
}


//归并排序
void MergeSort(int a[],int low,int high) {
    //如果待合并的数组长度为1,返回
    int length = high-low+1;
    if(length == 1)
        return;
    int mid = (low+high)/2;
    MergeSort(a,low,mid);
    MergeSort(a,mid+1,high);
    Merge(a,low,mid,high);
}

2.二分查找

Step1:Devide——将x与序列的中间元素比较

Step2:Conquer——(递归地)在子有序数列中查找x

Step3:Combine——nothing

T(n)=1*T(n/2)+O(1)=Θ(logn)

代码如下:

int BinarySearch(int a[], int low, int high, int expected) {
    if (low > high)
        return -1;
    int mid = (low + high) / 2;
    if (a[mid] == expected)
        return mid;
    if (a[mid] < expected)
        return BinarySearch(a, mid + 1, high, expected);
    else
        return BinarySearch(a, low, mid - 1, expected);
}

3.幂次方问题 (Powering a Num)

幂次方算法关键思想

T(n)=T(n/2)+O(1)=Θ(logn)

代码如下:

int Power(int x, int n) {
    if (n == 0)
        return 1;
    if (n == 1)
        return x;
    int t = Power(x, n / 2);
    if (n & 0x01 == 1)
        return t * t * x;
    else
        return t * t;

}

4.Fibonacci数列-平方递归法

这里写图片描述

归纳法得

这里写图片描述

2维方阵,计算过程中矩阵形式保持不变,而且二维方阵乘法是常数时间操作,

因此,该算法的时间复杂度与计算x^n类似,为:Θ(logn)

代码如下:

struct Matrix{
    int data[2][2];
};


//矩阵相乘
Matrix Mutiply(const Matrix& a, const Matrix& b) {
    Matrix c;
    for(int i=0;i<2;i++) {
        for(int j=0;j<2;j++) {
            c.data[i][j] = 0;
            for (int k = 0; k < 2; k++)
                c.data[i][j] += a.data[i][k] * b.data[k][j];
        }
    }
    return c;
}

//使用平方递归法
Matrix MatrixOprate(int n) {
    Matrix m;
    int data[2][2] = {{1,1},{1,0}};
    for(int i=0;i<2;i++)
        for(int j=0;j<2;j++)
            m.data[i][j] = data[i][j];
    if (n == 1)
        return m;
    Matrix t = MatrixOprate(n/2);//继续向下划分
    if(n & 0x01 == 1)//n为奇数
        return Mutiply(Mutiply(t,t),m);
    else//n为偶数
        return Mutiply(t,t);
}

//求第n位fibonacci数列的值
int Fibonacci(int n) {
    if (n <= 0)
        return 0;
    if (n == 1)
        return 1;
    Matrix m = MatrixOprate(n-1);
    return m.data[0][0];
}

5.矩阵乘积


5.1一般的矩阵乘法算法

若A为m×n矩阵,B为n×p矩阵,则他们的乘积AB会是一个m×p矩阵。其乘积矩阵的元素如下面式子得出:

这里写图片描述

显然,时间复杂度Θ(n)=n^3

代码如下:

const int MAXN=1000;
struct matrix{
    int n, m;
    double data[MAXN][MAXN];
};

int multiply(matrix& c, const matrix& a, const matrix& b){
    if (a.m != b.n)
        return 0;
    c.n = a.n;
    c.m = b.m;
    for (int i = 0; i < c.n; i++)
        for (int j = 0; j < c.m; j++) {
            c.data[i][j] = 0;
            for (int k = 0; k < a.m; k++)
                c.data[i][j] += a.data[i][k] * b.data[k][j];
        }
    return 1;
}

5.2 矩阵分块,实现分治

原理如下图所示:

分块思想

T(n)=8*T(n/2)+Θ(n^2),使用主定理求得Θ(n)=n^3,并没有什么卵用。



5.3斯特拉森算法,绝对的牛逼闪闪

考虑对T(n)=8*T(n/2)+Θ(n^2)这个递归式进行优化,显然,Θ(n^2)对应于矩阵的加法操作,并不能很好地优化,所以对8T(n/2)j进行优化,要么让8变小,要么让2变大,以使得n^logab小于3

而牛逼闪闪的斯特拉森就是推导出一套新的公式,使得8->7,实现了时间复杂度的优化,使其变为O(n^log2 7)约等于O(n^2.81)。

斯特拉森算法关键思想

代码略,(,,• ₃ •,,)(,,• ₃ •,,)(,,• ₃ •,,)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值