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] (1≤i≤j+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;
}