首页 > 试题广场 >

给定整数序列求连续子串最大和

[编程题]给定整数序列求连续子串最大和
  • 热度指数:2793 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 32M,其他语言64M
  • 算法知识视频讲解
给定无序整数序列,求连续非空子串最大和,例如{-23 17 -7 11 -2 1 -34},子串为{17,-7,11},最大和为21

输入描述:
输入为整数序列,数字用空格分隔,如:-23 17 -7 11 -2 1 -34


输出描述:
输出为子序列的最大和:21
示例1

输入

-23 17 -7 11 -2 1 -34

输出

21
nums =list(map(int,input().split()))
 
fori inrange(1,len(nums)):
    ifnums[i-1]>0:
        nums[i]+=nums[i-1]
print(max(nums))


发表于 2019-08-27 16:47:40 回复(1)
import java.util.Scanner;

/**
 * Dynamic Programming
 *
 * State:
 *   dp[i]: 以a[i]为结尾的连续子串的最大和
 *
 * Initial State:
 *   dp[0] = a[0]
 *
 * State Transition:
 *   if (dp[i - 1] >= 0) dp[i] = dp[i - 1] + a[i];
 *   else dp[i] = a[i];
 *
 * @author wylu
 */
public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        while (scanner.hasNext()) {
            String[] strs = scanner.nextLine().split(" ");
            int[] a = new int[strs.length];
            for (int i = 0; i < strs.length; i++) {
                a[i] = Integer.valueOf(strs[i]);
            }

            int[] dp = new int[a.length];
            dp[0] = a[0];
            int res = dp[0];
            for (int i = 1; i < a.length; i++) {
                dp[i] = (dp[i - 1] >= 0) ? dp[i - 1] + a[i] : a[i];
                res = Math.max(res, dp[i]);
            }
            System.out.println(res);
        }
    }
}

发表于 2019-01-11 11:06:29 回复(0)
动态规划,当遍历到arr[i]时,记dp为以arr[i-1]结尾时的最大和。如果它是非负数,就直接累加上arr[i]的值;如果是负数,那前面的累加做出的就是负贡献,需要重新开始dp=arr[i]累加。
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;

public class Main {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        String[] strArr = br.readLine().split(" ");
        if(strArr.length == 0){
            System.out.println(0);
        }else if(strArr.length == 1){
            System.out.println(Integer.parseInt(strArr[0]));
        }else{
            int[] arr = new int[strArr.length];
            for(int i = 0; i < arr.length; i++) arr[i] = Integer.parseInt(strArr[i]);
            int maxSum = arr[0];
            int dp = arr[0];
            for(int i = 1; i < arr.length; i++){
                dp = dp < 0? arr[i]: dp + arr[i];
                maxSum = Math.max(maxSum, dp);
            }
            System.out.println(maxSum);
        }
    }
}

发表于 2021-11-28 16:22:02 回复(0)
#include <bits/stdc++.h>
using namespace std;

int main(){
    int x, s=0, Max=INT_MIN;
    while(scanf("%d", &x)!=EOF){
        s += x;
        Max = max(Max, s);
        if(s<0)
            s = 0;
    }
    printf("%d\n", Max);
    return 0;
}

发表于 2020-11-03 00:38:13 回复(0)
if __name__ == '__main__':
    arr=list(map(int,input().split()))
    ans=min(arr)
    dp=[0] #判断将当前数加入子串还是从当前子串开始重新计算连续子串max(dp[-1]+a,a)  for a in arr:
        temp=max(dp[-1]+a,a)
        dp.append(temp)
        ans=max(ans,temp) print(ans)


发表于 2019-03-07 09:09:37 回复(0)
动归:时间复杂度o{n}
#include "stdio.h"
#include "limits.h"
#include <iostream>
using namespace std;
int main()
{
    int num;
    int ans = INT_MIN;
    int sum = 0;
    while(cin>>num)
    {
        sum += num;
        ans = max(ans, sum);
        if(sum<0)
            sum=0;
    }
    cout<<ans<<endl;
    return 0;
}

发表于 2019-01-23 14:37:49 回复(0)
package main

import (
    "fmt"
)

func main() {
    var x,sum,ans int
    fmt.Scan(&x)
    sum=x
    ans=x
    for{
        _,ok:=fmt.Scan(&x)
        if ok!=nil{
            break
        }
        if sum+x<x{
            sum=x
        }else{
            sum+=x
        }
        if sum>ans{
            ans=sum
        }
    }
    fmt.Print(ans)
}

发表于 2023-03-21 12:33:06 回复(0)

动态规划

  • O(n)时间复杂度
  • O(1)空间复杂度
  • 状态转移方程为 d[i] = max(d[i-1]+arr[i], a[i])
  • 用sum_tmp存储当前的d[i]
  • 用sum_max存储当前d[0]到d[i]的最大值
a = input().split()
a = [int(a[i]) for i in range(len(a))]
def max_subsequence(arr):
    length = len(arr)
    if length == 0:
        return 0
    if length == 1:
        return arr[0]
    sum_tmp = arr[0]
    sum_max = arr[0]
    for i in range(1, length):
        sum_tmp = max(sum_tmp + arr[i], arr[i])
        if sum_max < sum_tmp:
            sum_max = sum_tmp
    return sum_max
print(max_subsequence(a))
发表于 2021-03-18 11:22:46 回复(0)
#include<iostream>
#include<vector>
#include<algorithm>
int main()
{
    int n;
    std::vector<int>s;
    while(std::cin>>n)
    {
        
        
        
        s.push_back(n);
    }
    int N=s.size();
        std::vector<int>dp(N,0);
        dp[0]=s[0];
        
        for(int i=1;i<N;i++)
        {
            if(dp[i-1]<0)dp[i]=s[i];
            else dp[i]=std::max(dp[i],dp[i-1]+s[i]);
            
        }
        sort(dp.begin(),dp.end());
        std::cout<<dp[N-1]<<std::endl;

    
    return 0;
}
发表于 2020-09-18 11:51:18 回复(0)
分治策略。
思路:
求出左/右子表的最大子序列、求出跨越左右子表的最大子序列
选择三者中最大
#include<cstdio>

int max3(int a, int b, int c)
{
    if (a < b)
        a = b;
    if (a < c)
        return c;
    else 
        return a;
}

int maxSubSum (int a[], int left, int right)
{
    if (left == right) 
        return a[left];
    
    int i, mid;
    int maxLeftSum, maxRightSum;
    int maxMidSum1, maxMidSum2, sumer1, sumer2;
    
        //    求左、右子表最大子序列
    mid = (left + right) / 2;
    maxLeftSum = maxSubSum(a, left, mid);
    maxRightSum = maxSubSum(a, mid+1, right);
    

        //    求跨左右子表的最大子序列
    for (i = mid; i >= left; --i) {
        if (i == mid) {
            maxMidSum1 = sumer1 = a[i];
        } else {
            sumer1 += a[i];
            if (maxMidSum1 < sumer1)
                maxMidSum1 = sumer1;
        }
    }
    
    for (i = mid+1; i <= right; ++i) {
        if (i == mid+1) {
            maxMidSum2 = sumer2 = a[i];
        } else {
            sumer2 += a[i];
            if (maxMidSum2 < sumer2)
                maxMidSum2 = sumer2;
        }
    }
    
    return max3(maxLeftSum, maxRightSum, maxMidSum1+maxMidSum2);

}

int main ()
{
    int a[100];
    int n = 0;
    while (scanf("%d", &a[n++]) != EOF) ;
    printf("%d", maxSubSum(a, 0, n-2));
    return 0;
}
算法分析:
对应递推方程:
T(1) = 1
T(n) = 2T(n/2) + O(n)
由主方法求得T(n) = nlog2^n


穷举法,时间复杂度O(n)
#include<cstdio>
#include<vector>

using namespace std;

int main ()
{
    int tmp;
    vector<int> vec;
    
    while (scanf("%d", &tmp) != EOF)
        vec.push_back(tmp);
    
    //    算法逻辑
    int i, thisSum = 0, maxSum = vec[0];
    for (i = 0; i < vec.size(); ++i) {
        thisSum += vec[i];
        
        if (maxSum < thisSum)
            maxSum = thisSum;
        if (thisSum < 0)
            thisSum = 0;
    }
    printf("%d", maxSum);
    
    return 0;
}


编辑于 2020-08-04 19:49:55 回复(0)
简单dp
#include <bits/stdc++.h>
using namespace std;

int main()
{
	int z, _max;
	vector<int> vi;
	while (cin >> z)vi.push_back(z);
	int * dp = new int[vi.size()];
	dp[0] = vi[0];
	_max = dp[0];
	for (int i = 1; i < vi.size(); i++)
	{
		dp[i] = max(dp[i - 1] + vi[i], vi[i]);
		if (dp[i] > _max)_max = dp[i];
	}
	cout << _max;
}


发表于 2020-04-30 21:17:32 回复(0)
// 因为是连续的,所以可以两层循环,从i开始到j结束,每一轮存储一个a_max,a_max与max比较
var arr=readline().split(' ').map(Number);
var max=arr[0];
var len=arr.length;
for(var i=0;i<len-1;i++){
    var a_max=arr[i];
    // 存在一种情况就是 只有一个数 也就是不一定连续 可能单独一个数
    if(a_max>max){
        max=a_max;
    }
    for(var j=i+1;j<len;j++){
        a_max=a_max+arr[j];
        if(a_max>max){
            max=a_max;
        }
    }
}
print(max)
发表于 2020-02-15 19:05:58 回复(0)
while True:
    try:
        m = list(map(int,input().split()))
        sum = 0
        max = m[0]
        for i in m:
            if sum >= 0:
                sum += i
            else:
                sum = i
            if sum > max:
                max = sum
        print(max)
    except:
        break

编辑于 2019-08-27 14:01:33 回复(0)
sxm头像 sxm
list=list(map(int,input().split()))
conut=0
aa = []
for m in range(len(list)):
    conut = 0
    for i in list[0:m]:
        conut0= conut+i
        conut=conut0
        aa.append(conut)
    conut1 = 0
    for i in list[m:]:
        conut0= conut1+i
        conut1=conut0
        aa.append(conut1)
aa.sort(reverse=True)
print(aa[0])
发表于 2019-08-26 19:16:53 回复(0)
def maxSum(l):
    if len(l) == 1:
        return l[0]
    dp = l[:]     # dp中最终存储的是以当前字符结尾的最大数字
    for i in range(1, len(l)):
        if dp[i-1] > 0:
            dp[i] = dp[i-1] + l[i]   # 前一位置和大于0,加下去,否则另起炉灶
    return max(dp)
    
if __name__ == "__main__":
    l = list(map(int, input().split()))
    print(maxSum(l))

发表于 2019-03-25 20:52:22 回复(0)
//典型题目,因为是连续子串,因此我们根据当前位置是从头还是连续之前的来区分即可
#include <iostream>
#include <vector>
#include <limits.h>
using namespace std;
int main(){
    vector<int> vec;
    int num;
    while(cin>>num)
        vec.push_back(num);
    int res=INT_MIN,cur=0;
    for(int i=0;i<vec.size();++i){
        cur=max(cur+vec[i],vec[i]); //进行当前位置是否连续的讨论
        res=max(res,cur);
    }
    cout<<res;
     return 0;
}
 

编辑于 2019-02-26 15:57:26 回复(0)
#include<bits/stdc++.h>
using namespace std;

int main() {
    vector<int> vec;
    int a;
    while(cin>>a) {
        vec.push_back(a);
        if(cin.get() == '\n') break;
    }
    
    int size = vec.size();
    int max = vec[0], cursum = vec[0];
    
    for(int i = 1; i < size; i++){
        cursum = cursum + vec[i] > vec[i] ? cursum + vec[i] : vec[i];
        max = cursum > max ? cursum : max;
    }
    
    cout<<max<<endl;
    
    return 0;
}
发表于 2018-09-04 15:54:44 回复(0)
package 案例七;
import java.util.Scanner;
public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        String[] str = sc.nextLine().split(" ");
        int[] arrInt = new int[str.length];
        for(int i=0;i<arrInt.length;i++){
            arrInt[i] = Integer.parseInt(str[i]);
        }
        System.out.println(getMaxNum(arrInt));
    }

    private static int getMaxNum(int[] arrInt) {
        int n = arrInt.length;
        int[] dp = new int[n];
        dp[0] = arrInt[0];
        int max = dp[0];
        for(int i=1;i<n;i++){
            if(dp[i-1]<0){
                dp[i] = arrInt[i];
            }else{
                dp[i] = dp[i-1] + arrInt[i];
                max = Math.max(max, dp[i]);
            }
        }
        /*for(int i=0;i<n;i++){
            System.out.print(dp[i]+" ");
        }*/
        return max;
    }
}

发表于 2018-09-02 18:21:32 回复(0)
num=input()
num_list=[int(n) for n in num.split()]
temp=0
max_value=-100000
for i in range(len(num_list)):
    temp=max(temp+num_list[i],num_list[i])
    max_value=max(max_alue,temp)
print(max_value)


发表于 2018-08-25 20:14:08 回复(0)
#include<iostream>
using namespace std;
#include<vector>
#include<algorithm>


int FindGreatestSumOfSubArray(vector<int> array) {
        int len = array.size();
        if(len == 0)
            return 0;        //如果数组长度为0,返回0
        if(len == 1)
            return array.front();    //如果数组长度为1,返回唯一的元素
        vector<int> sum;    //存储数组每次累加的和值
        int max;    //最大的那个和值
        int i,j;        
        for(i = 0; i < len-1; i++)    //i从0到倒数第二位置
        {
            sum.push_back(array[i]);        //将数组首元素赋值给sum
            for(j = i+1; j < len; j++)
                sum.push_back(sum.back() + array[j]);    //将sum的最后一个元素和下一个数组元素进行相加,并插入到sum最后
        }
        sort(sum.begin(),sum.end());    //对每轮得到的和值进行排序,然后找到该轮的和的最大值
        max = sum.back();
        return max;
}

int main(void)
{
    vector<int> data;
    int swp;
   while(cin>>swp)
       data.push_back(swp);
    cout<<FindGreatestSumOfSubArray(data);
    return 0;
}

发表于 2018-08-24 00:07:21 回复(0)