递归策略(减而治之和分而治之)

来源:互联网 发布:应用更新软件 编辑:程序博客网 时间:2024/05/17 18:43

递归策略(减而治之和分而治之)

递归算法是把问题转化为规模缩小了的同类问题的子问题。然后递归调用函数(或过程)来表示问题的解。
接下来,我们将通过同一个问题来分析两种策略。

问题: 计算任意n个整数之和

减而治之

求解一个大规模的问题,可以将其划分为两个子问题,其一是平凡问题,另一个规模缩减。由子问题的解,得到原问题的解。

int sum(int A[], int n){    return (n < 1)?0:A[n-1]+sum(A,n-1);}

分而治之

求解一个大规模的问题,可以将其划分为多个(通常情况下为两个)子问题,两个问题的规模大体相同。由子问题的解,得到原问题的解。

int sum(int A[], int low, int high){return (low == high) ? A[low] : sum(A, low, (low + high) >> 1) + sum(A, ((low + high) >> 1) + 1, high);}

通过以上例子可以明显感觉到减而治之和分而治之的算法差别,接下来将通过一个例子进一步说明分而治之算法的优越性。

找出数组中最大的两个数A[low,high)

通常情况下,最直接也是最容易想到的方法是,将数组中数遍历一遍。具体的代码如下:

void max2(int A[], int low, int high, int &first, int &second){    first = low;    second = low + 1;    if (A[first] < A[second])        swap(first,second);    for (int i = low + 2; i < high;i++)    {        if (A[i] > A[second])        {            second = i;            if (A[second] > A[first])                swap(first, second);        }    }}

如果用分而治之的方法求解,代码如下:

void max2_recursion(int A[], int low, int high, int &first, int &second){    if (low + 2 == high)    {        if (A[low] > A[low + 1])        {            first = low;            second = low + 1;        }        else {            first = low +1;            second = low;        }        return;    }    if (low + 3 == high)    {        first = low;        second = low + 1;        if (A[first] < A[second])            swap(first, second);        if (A[low+2] > A[second])        {            second = low+2;            if (A[second] > A[first])                swap(first, second);        }    }    int mid = (low + high) >> 1;    int first_left, second_left, first_right,second_right;    max2_recursion(A, low, mid, first_left, second_left);    max2_recursion(A, mid, high, first_right, second_right);    if (A[first_left] > A[first_right])    {        first = first_left;        second = (A[second_left] > A[first_right]) ? second_left : first_right;    }    else {        first = first_right;        second = (A[second_right] > A[first_left]) ? second_right : first_left;    }}

由以上代码可以看出,分而治之的方法时间复杂度虽然还是o(n),但是明显更为简便。

原创粉丝点击