分治策略的实现

本文介绍了分治策略,包括其三个步骤:分解、解决和合并。详细讨论了最大子数组问题和矩阵乘法问题的分治解决方案,并阐述了解决递归式的代入法、递归树法和主方法。通过实例分析,展示了如何应用这些方法解决实际问题,例如最大子数组问题的时间复杂度为O(n*logn)。
摘要由CSDN通过智能技术生成

目录

前言

 分治策略的应用

最大子数组问题

矩阵乘法问题

求解递归式的三种方法

代入法求递归式

用递归树求递归式

主方法求递归式


前言

分治三个步骤:

分解:分解原问题为子问题,这些子问题为原问题的较小规模的问题。

解决:递归地解决这些子问题,如果规模小到一定程度,则直接得出答案。

合并:合并上述解决地子问题地解,得出最终解。

递归情况:当子问题规模比较大时,成为递归情况;

基本情况:当子问题规模不需要递归,已经触底时,此时称作基本情况。

递归式:刻画算法的运行时间的等式或者不等式,如归并排序中的最坏情况下的时间复杂

 分治策略的应用

最大子数组问题

最大子数组:一个数组中的非空连续的数组元素和最大的集合成为最大子数组。

a[4] = {-1,-2,3,4};

数组a的子数组有{-1},{-2},{3},{4},{-1,-2},{-2,3},{3,4},{-1,-2,3},

{-2,3,4},{-1,-2,3,4}.

其中{3,4}子数组的和为7,是这些数组中和最大的子数组。

代码:

#include "stdio.h"
#define MAXSIZE 100
#define MINNUM -10000
int *find_cross_max_subarray(int A[MAXSIZE], int low, int mid, int high);
int *find_maxium_subarray(int a[MAXSIZE], int low, int high);
int *max(int *x, int *y, int *z);
int result[3] = {0};

void main() {
    int A[6] = {-1,3,-2,5,-4, 6};
    find_maxium_subarray(A, 0, 5);
    printf("%d, %d, %d", result[0], result[1], result[2]);
}

int *find_cross_max_subarray(int A[MAXSIZE], int low, int mid, int high) {

    int sum = 0;
    int max_sum = 0;
    result[0] = MINNUM;
    for (int i = mid + 1; i <= high; i++)
    {
        sum = sum + A[i];
        if(result[0] < sum) {
            result[0] = sum;
            result[2] = i;
        }

    }
    max_sum = result[0];
    result[0] = MINNUM;
    sum = 0;
    for (int i = mid; i >= 0; i--)
    {
        sum = sum + A[i];
        if(result[0] < sum) {
            result[0] = sum;
            result[1] = i;
        }
    }
    result[0] = max_sum + result[0];
    return result;
}

int *find_maxium_subarray(int a[MAXSIZE], int low, int high) {
    if(low == high) {
        result[0] = a[low];
        result[1] = low;
        result[2] = high;
        return result;
    }
    int mid = (low+high)/2;
    //int right_res[3] = {0};
    //int left_res[3] = {0};

    int *left_res = find_maxium_subarray(a, low, mid);
    int *right_res = find_maxium_subarray(a, mid+1, high);
    int *cross_res = find_cross_max_subarray(a, low, mid, high);

    return max(left_res, right_res, cross_res);

}

int *max(int *x, int *y, int *z) {
 
    int *max = x;
 
    if(x[0] > y[0]) {
 
        max = x;
    } else{
 
        max = y;
 
    }
 
    if (z[0] > max[0]) {
        max = z;
    }
 
    return max;
}

 输出结果:

时间复杂度:O(n*lgn); 

矩阵乘法问题

前提:由于矩阵需要能够被分解成4个子矩阵运算,所以Strassen算法的前提条件式矩阵的长和宽n是2的幂函数。

代码:

#include "stdio.h"
#define MAXSIZE 4

void multiply_matrix(int a[MAXSIZE][MAXSIZE], int b[MAXSIZE][MAXSIZE], int c[MAXSIZE][MAXSIZE], int n, int i, int j);
int n = MAXSIZE;
void main() {
    int a[MAXSIZE][MAXSIZE] = {
        {1,2,3,4},
        {1,2,3,4},
        {1,2,3,4},
        {1,2,3,4}
    };
    int b[MAXSIZE][MAXSIZE] = {
        {1,1,1,1},
        {1,1,1,1},
        {1,1,1,1},
        {1,1,1,1}
    };
    int c[MAXSIZE][MAXSIZE] = {0};
    multiply_matrix(a, b, c, n, 0, 0);
}

void multiply_matrix(int a[MAXSIZE][MAXSIZE], int b[MAXSIZE][MAXSIZE], int c[MAXSIZE][MAXSIZE], int n, int i, int j) {
    int length = n/2;
    if(n == 1) {
        c[i][j] = a[i][j]*b[i][j];
    } else {
        multiply_matrix(a, b, c, length, i, j);
        multiply_matrix(a, b, c, length, i, j + length);
        multiply_matrix(a, b, c, length, i + length, j);
        multiply_matrix(a, b, c, length, i + length, j + length);
    }
    
}

求解递归式的三种方法

代入法:猜测一个边界,用数学归纳法证明这个边界的正确性;

递归树法:将递归式转化为一棵树,其结点表示不同层次的递归调用产生的代价,然后采用边界和技术求解递归式。

主方法:可求解如下递归式的界:

 递归式的技术细节:

代入法求递归式

  1. 猜测解的形式;
  2. 使用数学归纳法证明解中常数,并证明解是正确的。

用递归树求递归式

猜测解的形式有时候会比较棘手,所以可以通过递归树的方法来需求解的形式。

主方法求递归式

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值