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;
}