题意是给一个长度为n的数组,求长度不超过m的子数组元素之和的最大值。
结果老是不对,希望大神们能指点指点,感激不尽!!!
我的想法是开一个队列,每次读入的时候sum就加上读入这个的值,如果这个sum小于0了就将读入的队列全部出队,每次用sum和ans比较,如果sum>ans,就更新ans的值,最后结果就是答案了,可是数据一大,结果就不对了。
#include<iostream>
#include<queue>
#include<algorithm>
using namespace std;
int n, m;
int value[100010] = {0};
int MIN[100010] = { 0 };
int qianzhui[100010] = { 0 };
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
queue<long long>s;
long long sum = 0, ans = 0;
cin >> n >> m;
for (int i = 1; i <= n; i++)
cin >> value[i];
if (*max_element(value + 1, value + 1 + n) <= 0)
{
cout << *max_element(value + 1, value + 1 + n);
return 0;
}
for (int i = 1; i <= n; i++)
{
if (s.size() < m)
{
s.push(value[i]);
sum += value[i];
if (sum < 0)
{
while (!s.empty())
s.pop();
sum = 0;
continue;
}
if (sum > ans)
ans = sum;
}
else
{
sum -= s.front();
s.pop();
s.push(value[i]);
sum += value[i];
if (sum < 0)
{
while (!s.empty())
s.pop();
sum = 0;
continue;
}
if (sum > ans)
ans = sum;
}
}
for (; !s.empty();)
{
sum -= s.front();
s.pop();
if (sum > ans)
ans = sum;
}
cout << ans;
}
这个虽然看着复杂一点,但是思路比较清晰,后面不懂的朋友也可以看看
#include<queue>
#include <iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
struct total
{
ll x;//x是其值
int y;//y为其位置
}p[100010];
int n, m;
ll a;
ll sum[100010] = { 0 };
ll max(ll x, ll y);
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cin >> n >> m;
for (int i = 1; i <= n; i++)
{
cin >> a;
sum[i] = sum[i - 1] + a;
p[i].x = sum[i];
p[i].y = i;
}
deque <total> b;
b.push_back({ 0,0 });
ll ans = p[1].x;
for (int i = 1; i <= n; i++)
{
while (!b.empty() && p[i].y - b.front().y > m)
{
b.pop_front();
}
if (!b.empty() && p[i].x > b.back().x)
{
b.push_back(p[i]);
}
else {
while (!b.empty() && p[i].x < b.back().x)
b.pop_back();
b.push_back(p[i]);
}
if (b.size() != 1)
ans = max(ans, (b.back().x) - (b.front().x));
else ans = max(ans, b.back().x);
}
cout << ans;
return 0;
}
ll max(ll x, ll y)
{
if (x > y)
return x;
else return y;
}
我用java写了一个demo
public static void main(String[] args) {
Integer[] list = new Integer[]{1,3,5,23,12,1,54,23,5,32,52,52, 1, 1, 1};
getSubListMaxSum(list, 4);
}
private static void getSubListMaxSum(Integer[] list, int m) {
// m 长度的子数组
Integer[] subList = new Integer[m];
// 子数组元素之和最大值
Integer subListSumMax = 0;
// 填充子数组
for (int subListIndex = 0; subListIndex < subList.length; subListIndex++) {
subListSumMax += list[subListIndex];
subList[subListIndex] = list[subListIndex];
}
System.out.println("初始数组:" + Arrays.toString(subList) + ", 最大值:" + subListSumMax);
// 新的子数组的最大值
Integer newSubListSum;
// 遍历 list[m] 下标开始的数据,比较新旧子数组的值
for (int listIndex = m; listIndex < list.length; listIndex++) {
// 将子数组中的第一个元素取出,然后从list中读取一个新值
// 用上一轮记录的 子数组元素之和最大值 - 子数组第一个值 + list中新值 = 新的子数组的最大值
newSubListSum = subListSumMax - subList[0] + list[m];
if (subListSumMax < newSubListSum) {
subListSumMax = newSubListSum;
}
// 用来截取新的子数组
int listSubIndex = listIndex - m + 1;
// 更新subList中的数据
for (int subListIndex = 0; subListIndex < m; subListIndex++) {
subList[subListIndex] = list[listSubIndex++];
}
System.out.println("中间数组:" + Arrays.toString(subList) + ", 最大值:" + subListSumMax);
}
System.out.println("结束数组:" + Arrays.toString(subList) + ", 最大值:" + subListSumMax);
}
你的sum,队列s都是long long型的,但是他们有时候加进去的数是value[i],而value[i]是int型,会不会是这个类型转换出问题了?你把value[i]改成long long试试
#include
using namespace std;
int main()
{
long m,n,i,j,k,startid,endid;
long long sum = 0, ans = 0;
int * value;
cin >> n >> m;
value = new int[n]; // 根据输入构建原数组
for (int i = 0; i < n; i++)
cin >> value[i];
ans = value[0]; // 子数组和初值
for(i=0;i<n;i++) // 原数组元素遍历
{
for(j=i;j<i+m&&j<n;j++) // 构成元素个数不大于m的子数组
{
sum = 0;
for(k=i;k<j;k++) // j-i个元素子数组求和
sum += value[k];
if(sum>ans) // 取子数组和的最大值并记录该子数组的讫止位
{
startid = i;
endid = j - 1;
ans = sum;
}
}
}
cout << "子数组最大和="<<ans<<endl;
cout<<"最大和子数组讫始位置:"<<startid<<" 结束位置:"<<endid<<endl;
for(i=startid;i<endid;i++) cout<<value[i]<<",";
delete []value;
cin>>i; // 只是暂停
你原来的程序有点小问题,n个元素的数组,下标是从0至n-1,关于子数组最大和的问题,网上有很多方法,我这只是其中一种,比较好理解,但不是最优的。