k长连续子段和

最优解法

解法1:动态规划
表示以位置为结尾,长度大于等于的所有子段中最大的子段和。那么考虑转移:
以位置为结尾的大于等于k的子段分为两种:

  1. 长度刚好等于,这种情况下最大子段和等于这个数字的和
  2. 长度大于,这种情况下最大子段和等于

需要前缀和数组和dp数组辅助求解,空间复杂度,时间复杂度

long long dp[100005];
long long sum[100005];
long long solve(int n, int k, vector<int> &a){
    assert(a.size() == n);
    memset(dp, 0, sizeof dp);
    sum[0] = a[0];
    for(int i = 1; i < n; ++i) sum[i] = sum[i-1] + a[i];
    dp[k-1] = sum[k-1];
    long long ans = dp[k-1];
    for(int i = k; i < n; ++i){
        dp[i] = sum[i]-sum[i-k];
        dp[i] = max(dp[i-1]+a[i], dp[i]);
        ans = max(ans, dp[i]);
    }return ans;
}

解法2:前缀和
求出前缀和数组,长度大于等于就要求选择的两个前缀和距离必须大于等于
那么枚举右端点,子段和等于要小于等于。那么另一个指针维护一下的最小值即可。
需要前缀和数组求解,空间复杂度,时间复杂度

long long sum[100005];
long long solve(int n, int k, vector<int> &a){
    assert(a.size() == n);
    sum[0] = a[0];
    for(int i = 1; i < n; ++i) sum[i] = sum[i-1] + a[i];
    long long ans = sum[k-1];
    int p = 0;
    for(int i = k; i < n; ++i){
        long long x = sum[i]-sum[i-k];
        sum[p+1] = min(sum[p], sum[p+1]);p++;
        ans = max(ans, x);
    }return ans;
}
全部评论

相关推荐

牛客279957775号:铁暗恋
点赞 评论 收藏
分享
点赞 评论 收藏
分享
预计下个星期就能开奖吧,哪位老哥来给个准信
华孝子爱信等:对接人上周说的是这周
点赞 评论 收藏
分享
点赞 收藏 评论
分享
牛客网
牛客企业服务