《算法导论》课后题--5--第四章(0)

来源:互联网 发布:奥数优化训练22讲 编辑:程序博客网 时间:2024/06/05 21:04

4.1-1

分析:

当A的所有元素都为负数时,该函数返回数组中的最大元素该元素的下标

-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------

4.1-2

分析:该题是对课本内容的小练习,继续学习伪代码书写;

作答:

//输入:待查找的数组A//输出:最大子数组的下标范围及和FIND-MAXIMUM-SUBARRAY(A)1low = 1//low用来存储最大子数组的下界2high = 1//high用来存储最大子数组的上界3maxSum = 负无穷//存储最大子数组的和4for i = 1 to A.length5sum = 0//累计当前求和结果6for j = i to A.length7sum += A[j]8if sum > maxSum9maxSum = sum10low = i11high = j12return (low, high, maxSum)
两层循环嵌套,容易求得渐进时间复杂度为:
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------

4.1-3

分析:考查将伪代码转化成程序,并对现有算法进行复合改进;

作答:

#include <iostream>#include <vector>#include <ctime>using namespace std;//计算函数时间clock_t beginA, endA, beginB, endB;double durationA, durationB;void findMaximumSubarray(vector<int> &A, int &low, int &high, int &maxSum){    low = 1;    high = 1;    maxSum = -999999;    for (int i = 0; i < A.size(); ++i)    {        int sum = 0;        for (int j = i; j < A.size(); ++j)        {            sum += A[j];            if (sum > maxSum)            {                maxSum = sum;                low = i;                high = j;            }        }    }}void findMaxCrossingSubarray(vector<int> &A, int low, int mid, int high, int &maxLeft, int &maxRight, int &maxSum){    int leftSum = -999999;    int sum = 0;    for (int i = mid; i >= low; --i)    {        sum += A.at(i);        if (sum > leftSum)        {            leftSum = sum;            maxLeft = i;        }    }    int rightSum = -999999;    sum = 0;    for (int j = mid + 1; j <= high; ++j)    {        sum += A.at(j);        if (sum > rightSum)        {            rightSum = sum;            maxRight = j;        }    }    maxSum = leftSum + rightSum;}void findMaximumSubarray(vector<int> &A, int low, int high, int &fLow, int &fHigh, int &fSum){    if (high == low)    {        fLow = low;        fHigh = low;        fSum = A.at(low);    }    else    {        int mid = (low + high) / 2;        int leftLow, leftHigh, leftSum;        findMaximumSubarray(A, low, mid, leftLow, leftHigh, leftSum);        int rightLow, rightHigh, rightSum;        findMaximumSubarray(A, mid + 1, high, rightLow, rightHigh, rightSum);        int crossLow, crossHigh, crossSum;        findMaxCrossingSubarray(A, low, mid, high, crossLow, crossHigh, crossSum);        if (leftSum >= rightSum && leftSum >= crossSum)        {            fLow = leftLow;            fHigh = leftHigh;            fSum = leftSum;        }        else if (rightSum >= leftSum && rightSum >= crossSum)        {            fLow = rightLow;            fHigh = rightHigh;            fSum = rightSum;        }        else        {            fLow = crossLow;            fHigh = crossHigh;            fSum = crossSum;        }    }}int main(int argc, char *argv[]){    //vector<int> A{ 13, -3, -25, 20, -3, -16, -23, 18, 20, -7, 12, -5, -22, 15, -4, 7 };    for(int i = 10 ; i < 300 ; ++i)    {        vector<int> A(i, 1);        vector<int> B = A;        //测试暴力算法        int Alow, Ahigh, Asum;        beginA = clock();        findMaximumSubarray(A, Alow, Ahigh, Asum);        endA = clock();        durationA = double(endA - beginA) / CLK_TCK;        //测试递归算法        int Blow, Bhigh, Bsum;        beginB = clock();        findMaximumSubarray(B, 0, B.size() - 1, Blow, Bhigh, Bsum);        endB = clock();        durationB = double(endB - beginB) / CLK_TCK;        if((endA - beginA) == (endB - beginB))        {            cout << "when input scale is i = " << i << endl;            cout << "sum: " << Asum << " ,and runtime is : " << durationA << endl;            cout << "sum: " << Bsum << " ,and runtime is : " << durationB << endl;        }    }    return 0;}
测试结果:(只显示了最后一次输出的结果),大约在当数组规模是230左右时,两种算法计算时间相当。

编译环境:Qt Creator + VS2015

-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------

4.1-4

分析:对算法进行改进;

作答:

伪代码:

//当数组中的元素都为负数时,返回空数组,//此时返回的下标low > high,注意把函数输入下标和返回下标不要混淆FIND-MAXIMUM-SUBARRAY(A, low, high)1if high == low2if A[low] >= 03return (low, high, A[low])4else return (low, high-1, 0) //此时low > high,表示返回空数组5else mid = (low + high) / 26(left-low, left-high, left-sum) = FIND-MAXIMUM-SUBARRAY(A, low, mid)7(right-low, right-high, right-sum) = FIND-MAXIMUM-SUBARRAY(A, mid+1, high)8(cross-low, cross-high, cross-sum) = FIND-MAX-CROSSING-SUBARRAY(A, low, mid, high)9if left-sum >= right-sum and left-sum >= cross-sum10return (left-low, left-high, left-sum)11elseif right-sum >= left-sum and right-sum >= cross-sum12return (right-low, right-high, right-sum)13else return (cross-low, cross-high, cross-sum)FIND-MAX-CROSSING-SUBARRAY(A, low, mid, high)1left-sum = 02max-left = mid + 13sum = 04for i = mid downto low5sum += A[i]6if sum >= left-sum//等号保证出现0元素时返回07left-sum = sum8max-left = i9right-sum = 010max-right = mid11sum = 012for j = mid+1 to high13sum += A[j]14if sum >= right-sum15right-sum = sum16max-right = j17return (max-left, max-right, left-sum + right-sum)
代码实现:

#include <iostream>#include <vector>using namespace std;void findMaxCrossingSubarray(vector<int> &A, int low, int mid, int high, int &maxLeft, int &maxRight, int &maxSum){    int leftSum = 0;    maxLeft = mid + 1;    int sum = 0;    for (int i = mid; i >= low; --i)    {        sum += A.at(i);        if (sum >= leftSum)        {            leftSum = sum;            maxLeft = i;        }    }    int rightSum = 0;    maxRight = mid;    sum = 0;    for (int j = mid + 1; j <= high; ++j)    {        sum += A.at(j);        if (sum >= rightSum)        {            rightSum = sum;            maxRight = j;        }    }    maxSum = leftSum + rightSum;}void findMaximumSubarray(vector<int> &A, int low, int high, int &fLow, int &fHigh, int &fSum){    if (high == low)    {        if(A.at(low) >= 0)        {            fLow = low;            fHigh = low;            fSum = A.at(low);        }        else        {            fLow = low;            fHigh = high - 1;            fSum = 0;        }    }    else    {        int mid = (low + high) / 2;        int leftLow, leftHigh, leftSum;        findMaximumSubarray(A, low, mid, leftLow, leftHigh, leftSum);        int rightLow, rightHigh, rightSum;        findMaximumSubarray(A, mid + 1, high, rightLow, rightHigh, rightSum);        int crossLow, crossHigh, crossSum;        findMaxCrossingSubarray(A, low, mid, high, crossLow, crossHigh, crossSum);        if (leftSum >= rightSum && leftSum >= crossSum)        {            fLow = leftLow;            fHigh = leftHigh;            fSum = leftSum;        }        else if (rightSum >= leftSum && rightSum >= crossSum)        {            fLow = rightLow;            fHigh = rightHigh;            fSum = rightSum;        }        else        {            fLow = crossLow;            fHigh = crossHigh;            fSum = crossSum;        }    }}int main(int argc, char *argv[]){    vector<int> A(10, -1);    int Alow, Ahigh, Asum;    findMaximumSubarray(A, 0, A.size() - 1, Alow, Ahigh, Asum);    cout << "The maximum subarray is : ";    if(Alow > Ahigh)    {        cout << "null array!!!";    }    else    {        for(int i = Alow ; i <= Ahigh ; ++i)        {            cout << A.at(i) << " ";        }    }    cout << endl << "The sum is : " << Asum << endl;    return 0;}
输出结果:


-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------

好了,这一篇先到这里。下午继续。。。

加油!!!奋斗

0 0
原创粉丝点击