第四章 4.1最大子數組問題(分治)

4.1-1 當A的所有元素均爲負數時,FIND-MAXIMUM-SUBARRAY返回什麼?

最小負數值,及其下標

4.1-2 對最大子數組問題,編寫暴力求解方法的僞代碼,其運行時間應該爲θ(n2)

可運行代碼如下:

#include "stdafx.h"
#include<stdlib.h>
class Solve
{
public:
    Solve();
    int begin;
    int end;
    int sum;

};
Solve::Solve()
    {
        begin=0;
        end=0;
        sum=-65535;
    }
int _tmain(int argc, _TCHAR* argv[])
{
    int A[]={13,-3,-25,20,-3,-16,-23,18,20,-7,12,-5,-22,15,-4,7};
    //暴力求解算法
    int sum=0;
    Solve solve;
    int size=sizeof(A)/sizeof(A[0]);
    for(int i=0;i<size;i++)
    {
        sum=0;
        for(int j=i;j<size;j++)
        {
            sum+=A[j];
            if(sum>solve.sum)
            {
                solve.begin=i;
                solve.end=j;
                solve.sum=sum;
            }
        }
    }
    printf("彩票買入爲:第%d天;彩票賣出爲:第%d天;淨賺:%d元;\n",solve.begin+1,solve.end+1,solve.sum);
    system("pause");
    return 0;
}

4.1-3 在你的計算機上實現最大子數組問題的暴力算法和遞歸算法。請指出多大的問題規模n0 是性能交叉點——從此之後遞歸算法將擊敗暴力算法?然後,修改遞歸算法的基本情況——當問題規模小於n0 時採用暴力算法。修改後,性能交叉點會改變麼?

遞歸算法實現如下:

// test4.cpp : 定義控制檯應用程序的入口點。
//

#include "stdafx.h"
#include<stdlib.h>
class Solve
{
public:
    Solve();
    int begin;
    int end;
    int sum;

};
Solve::Solve()
    {
        begin=0;
        end=0;
        sum=-65535;
    }
Solve findCrossing(int *A,int low,int mid,int high)
{
    //確定左側的起始點
    Solve solveleft;
    solveleft.sum=-65535;
    int sum=0;
    for(int i=mid;i>=low;i--)
    {
        sum+=A[i];
        if(sum>solveleft.sum)
        {
            solveleft.sum=sum;
            solveleft.begin=i;
            solveleft.end=mid;//條理上清晰,不加這條語句也可以
        }
    }
    //確定右側的終點
    Solve solveright;
    solveright.sum=-65535;
    sum=0;
    for(int i=mid+1;i<=high;i++)
    {
        sum+=A[i];
        if(sum>solveright.sum)
        {
            solveright.sum=sum;
            solveright.end=i;
            solveright.begin=mid;//條理上清晰,不加這條語句也可以
        }
    }
    Solve solve;
    solve.begin=solveleft.begin;
    solve.end=solveright.end;
    solve.sum=solveleft.sum+solveright.sum;
    return solve;
}

Solve findMax(int *A,int low,int high)
{
    Solve solve;
    if(high==low)
    {
        solve.begin=low;
        solve.end=high;
        solve.sum=A[low];
        return solve;
    }
    else
    {
        int mid=(low+high)/2;
        Solve solveleft=findMax(A,low,mid);
        Solve solveright=findMax(A,mid+1,high);
        Solve solvecross=findCrossing(A,low,mid,high);
        if(solveleft.sum>=solveright.sum&&solveleft.sum>=solvecross.sum)
        {
            return solveleft;
        }
        else if(solveright.sum>=solveleft.sum&&solveleft.sum>=solvecross.sum)
        {
            return solveright;
        }
        else
        {
            return solvecross;
        }
    }
}
int _tmain(int argc, _TCHAR* argv[])
{
    int A[]={13,-3,-25,20,-3,-16,-23,18,20,-7,12,-5,-22,15,-4,7};
    int size=sizeof(A)/sizeof(A[0]);
    Solve solve=findMax(A,0,size-1);
    printf("彩票買入爲:第%d天;彩票賣出爲:第%d天;淨賺:%d元;\n",solve.begin+1,solve.end+1,solve.sum);
    system("pause");
    return 0;
}

4.1-4 假定修改最大子數組的定義,允許結果爲空子數組,其和爲0。你應該如何修改現有的算法,使他們能允許空子數組爲最終結果?

在最後輸出結果前,加一條判斷,如果solve.sum<0,則結果爲空數組,其和爲0。
或者sum的最小值不是-65535,而是0。

4.1-5 使用如下思想爲最大子數組問題設計一個非遞歸的、線性時間的算法。從數組的左邊界開始,由左至右處理,記錄到目前爲止已經處理過得最大子數組。若已知A[1…j]的最大子數組,基於如下性質將解擴展爲A[1…j+1]的最大子數組:A[1…j+1]的最大子數組要麼是A[1…j]的最大子數組,要麼是某個子數組A[i…j+1] (1ij+1 )。在已知A[1…j]的最大子數組的情況下,可以在線性時間內找到形如A[i…j+1]的最大子數組。

int _tmain(int argc, _TCHAR* argv[])
{
    int A[]={13,-3,-25,20,-3,-16,-23,18,20,-7,12,-5,-22,15,-4,7};
    int size=sizeof(A)/sizeof(A[0]);
    //線性時間算法。
    int sum=0;
    Solve solve;
    for(int i=0;i<size;i++)
    {
        sum=0;
        for(int j=i+1;j>=0;j--)
        {
            sum+=A[j];
            if(sum>solve.sum)
            {
                solve.begin=j;
                solve.end=i+1;
                solve.sum=sum;
            }
        }
    }
    printf("彩票買入爲:第%d天;彩票賣出爲:第%d天;淨賺:%d元;\n",solve.begin+1,solve.end+1,solve.sum);
    system("pause");
    return 0;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章