最大连续子序列和问题python,动态规划之求连续子序列最大值,最大和等问题

最近笔试做到两道涉及到求给定序列满足某某条件连续子序列的题目,在此总结一下,一道是声网的笔试题,一道是网易互联网笔试的第三道编程题。

网易互联网

1.题目

给定一个长度为n的数字序列,对于每个1<=k<=n,求解出所有长度为k的连续子序列的最大值中的最小值。

输入:

第一行数字n代表数字序列长度

第二行为n个序列元素

输出:

当k分别为1-n时,长度为k的连续子序列的最大值的最小值

例如,输入:

6

1 3 2 4 6 5

输出:1 3 3 4 6 6

2.思路

可以定义一个dp二维矩阵,规模为M*N,其中M,N均等于序列num的长度n,dp[i][j]代表从序号i到序号j的连续子序列中的最大值。初始值为0。整个程序可以分成两步:step1:填充dp矩阵,step2:查询dp矩阵。

(1)填充dp矩阵

初始值用memset设为0

当i==j 时,dp[i][j]==num[i]

其余情况:dp[i][j]=max(dp[i][j-1],dp[j][j])

以例子中的输入为例,可得dp矩阵如下图:

0

1

2

3

4

5

0

1

3

3

4

6

6

1

3

3

4

6

6

2

2

4

6

6

3

4

6

6

4

6

6

5

5

(2)查询dp矩阵

将长度为k的连续子序列的最大值入vector max中

对max sort一下,取最小值即为长度为k的连续子序列最大值的最小值

3.代码

#include

#include

#include

using namespace std;

#define M 100

#define N 100

int dp[M][N];

void fullTheDP(vector num){

int len = num.size();

//对角线上的元素为num中每个数本身的值

for (int i = 0; i < len; i++)

dp[i][i] = num[i];

//只需填充dp矩阵的右上角即可,dp[i][j]表示从num中从序号i到序号j的子序列的最大值

for (int i = 0; i < len - 1; i++)

for (int j = i + 1; j < len; j++)

dp[i][j] = max(dp[i][j - 1], dp[j][j]);

return;

}

void findTheMinOfMaxOfK(int k, int len){

vector max;

for (int i = 0; i < len - k + 1; i++)

{

max.push_back(dp[i][i + k - 1]);

}

sort(max.begin(), max.end());

cout << max[0] << ' ';

}

int main(){

//处理输入

int n;

cin >> n;

int i = n;

vector num;

while (i--)

{

int tmp;

cin >> tmp;

num.push_back(tmp);

}

//填充dp矩阵

memset(dp, 0, sizeof(dp));

fullTheDP(num);

//查询并输出

int k = 1;

while (k <= n)

{

findTheMinOfMaxOfK(k, n);

k++;

}

cout << endl;

return 0;

}

复制代码

声网

1.题目

给定一个数字序列A1,...,An,求i,j,使得Ai+...+Aj最大,并输出这个最大和。

样例:

输入:

6

-2,11,-4,13,-5,-2

输出:

20

2.思路

可以定义一个dp二维矩阵,规模为M*N,其中M,N均等于序列num的长度n,dp[i][j]代表从序号i到序号j的连续子序列的和。初始值为0。整个程序可以分成两步:step1:填充dp矩阵,并用整数max存最大值以及ibegin,iend存最大和序列的开始终止序号;step2:输出,max为最大和,ibegin和iend为和为最大值的子序列的开始/结束下标。

(1)填充dp矩阵

初始值用memset设为0

当i==j 时,dp[i][j]==num[i]

其余情况:dp[i][j]=dp[i][j-1]+num[j]

(2)输出

3.代码

#include

#include

#include

using namespace std;

#define M 100

#define N 100

int dp[M][N];

void findTheMaxSumSeq(vector num){

//填充dp

int len = num.size();

int maxNum =num[0];

int ibegin = 0, iend = 0;

//只需填充dp矩阵的右上角即可,对角线上的元素为num中每个数本身的值,dp[i][j]表示从num中从序号i到序号j的子序列的最大值

for (int i = 0; i < len ; i++)

for (int j = i ; j < len; j++)

{

if (i == j)

{

dp[i][j] = num[i];

if (dp[i][j] > maxNum)

{

maxNum = dp[i][j];

ibegin = i;

iend = j;

}

}

else

{

dp[i][j] = dp[i][j - 1] + num[j];

if (dp[i][j] > maxNum)

{

maxNum = dp[i][j];

ibegin = i;

iend = j;

}

}

}

cout << maxNum << endl;//输出最大和

for (int i = ibegin; i <= iend; i++)//输出最大和对应的子序列

cout << num[i] << ' ';

cout << endl;

}

int main(){

//处理输入

int n;

cin >> n;

int i = n;

vector num;

while (i--)

{

int tmp;

cin >> tmp;

num.push_back(tmp);

}

//查找最大和子序列

findTheMaxSumSeq(num);

return 0;

}

复制代码

没有测试很多用例,若有考虑不周的地方,望指出~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值