列表

详情


DP9. 环形数组的连续子数组最大和

描述

给定一个长度为 n 的环形整数数组,请你求出该数组的 非空 连续子数组 的最大可能和 。

环形数组 意味着数组的末端将会与开头相连呈环状。例如,对于数组 而言,第一个数 1的前一个数是最后一个数 -4

输入描述

第一行输入一个正整数 n ,代表数组的长度。
第二行为 n 个整数 a_i,每个整数之间用空格隔开,代表数组的各个元素。


输出描述

输出一个整数,为原数组的非空子数组的最大可能和。

示例1

输入:

3
5 -3 5

输出:

10

说明:

从子数组 [5,5] 得到最大和 5 + 5 = 10

示例2

输入:

4
3 -2 2 -3

输出:

3

说明:

从子数组 [3] 和 [3,-2,2] 都可以得到最大和 3

原站题解

C++ 解法, 执行用时: 12ms, 内存消耗: 924KB, 提交时间: 2022-05-02

#include<bits/stdc++.h>
using namespace std;
int n,t,sum,dpmax=INT_MIN,dpmin=INT_MAX;
int main(){
    scanf("%d",&n);
    int tmax=dpmax,tmin=dpmin;
    for(int i=1;i<=n;i++){
        scanf("%d",&t);
        sum+=t;
        tmax=max(tmax+t,t);
        tmin=min(tmin+t,t);
        dpmax=max(dpmax,tmax);
        dpmin=min(dpmin,tmin);
    }
    if(dpmax>=0&&dpmax+dpmin<sum)dpmax=sum-dpmin;
    printf("%d\n",dpmax);
    return 0;
}

C 解法, 执行用时: 13ms, 内存消耗: 684KB, 提交时间: 2022-04-02

#include<stdio.h>
int findmax(int a, int b) {
    if(a>b) return a;
    return b;
}
int findmin(int a, int b) {
    if(a<b) return a;
    return b;
}
int main() {
    int n;
    scanf("%d",&n);
    int num[n];
    for(int i=0;i<n;i++) {  
        scanf("%d",&num[i]);
    }
    int curmax=0,maxSum=num[0],curmin=0,minSum=num[0],tot=0;
    for(int i=0; i<n; i++) {
        tot += num[i];
        curmax = findmax(curmax+num[i], num[i]);
        maxSum = findmax(curmax, maxSum);
        curmin = findmin(curmin+num[i], num[i]);
        minSum = findmin(curmin, minSum);
    }
    if(maxSum < 0) {
        printf("%d",maxSum);
    }
    else {
        printf("%d",findmax(maxSum, tot - minSum));
    }
    
    return 0;
}

C++ 解法, 执行用时: 13ms, 内存消耗: 792KB, 提交时间: 2022-03-27

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
int a[100000];
int main(){
    IOS;
    int n,s=0,maxs=INT_MIN,mins=INT_MAX,tmax=0,tmin=0;
    cin>>n;
    for(int i=0;i<n;i++)
        cin>>a[i];
    for(int i=0;i<n;i++){
        s+=a[i];
        tmax=max(tmax+a[i],a[i]);
        tmin=min(tmin+a[i],a[i]);
        maxs=max(maxs,tmax);
        mins=min(mins,tmin);
    }
    cout<<(maxs>0?max(maxs,s-mins):maxs);
    return 0;
}

Go 解法, 执行用时: 13ms, 内存消耗: 5204KB, 提交时间: 2022-04-01

package main

import (
    "bufio"
    "os"
    "fmt"
    "strconv"
    "strings"
    "math"
)

// 1.求出[1-n]之间连续最长子序列和
// 2.如果最长序列和是包括首尾,那反之除去这部分的序列是连续最小子序列和
//   那么就找最小子序列和即可,用[1-n]序列和来减去最小子序列
// 比较1和2谁更大

func main(){
    input :=bufio.NewScanner(os.Stdin)
    buf :=make([]byte,20000*1024)
    input.Buffer(buf,len(buf))
    for input.Scan(){
        n,_ :=strconv.Atoi(input.Text())
        input.Scan()
        str := strings.Split(input.Text()," ")
        data :=make([]int,n+1)
        for i:=0;i<n;i++{
            temp,_ :=strconv.Atoi(str[i])
            data[i+1] = temp
        }
        dp := data[1]
        maxDp :=dp
        sumData :=dp
        for i:=2;i<=n;i++{
            sumData += data[i]
            // 计算当前dp
            dp = data[i] + int(math.Max(float64(dp),float64(0)))
            maxDp = int(math.Max(float64(maxDp),float64(dp)))
        }
        // 找当前序列的最短子序列和
        dp = data[1]
        minDp :=0
        for i:=2;i<n;i++{
            // 计算当前dp
            dp = data[i] + int(math.Min(float64(dp),float64(0))) // 加负数越加越小
            minDp = int(math.Min(float64(minDp),float64(dp)))
        }
        fmt.Println(int(math.Max(float64(maxDp),float64(sumData-minDp))))
    }
}

C 解法, 执行用时: 14ms, 内存消耗: 644KB, 提交时间: 2022-04-29

#include<stdio.h>

int findmax(int a, int b) {
    if(a>b) return a;
    return b;
}
int findmin(int a, int b) {
    if(a<b) return a;
    return b;
}
int main() {
    int n;
    scanf("%d",&n);
    int num[n];
    for(int i=0;i<n;i++) {  
        scanf("%d",&num[i]);
    }
    int curmax=0,maxSum=num[0],curmin=0,minSum=num[0],tot=0;
    for(int i=0; i<n; i++) {
        tot += num[i];
        curmax = findmax(curmax+num[i], num[i]);
        maxSum = findmax(curmax, maxSum);
        curmin = findmin(curmin+num[i], num[i]);
        minSum = findmin(curmin, minSum);
    }
    if(maxSum < 0) {
        printf("%d",maxSum);
    }
    else {
        printf("%d",findmax(maxSum, tot - minSum));
    }
    
    return 0;
}

上一题