题目概述:
给定一个长度为 n 的数组,数组中的数为整数。
请你选择一个非空连续子数组,使该子数组所有数之和尽可能大。求这个最大值。
输入描述:
第一行为一个正整数 n,代表数组的长度。 1<= n <=2*10^5
第二行为 n 个整数 ai,用空格隔开,代表数组中的每一个数。
输出描述:
连续子数组的最大之和。
示例1:
输入:
3
3 -4 5
输出:
5
说明:
选择 [5] 这个子数组即可。
算法思路:
对于该题,想要得到连续子数组的最大和,那么对于当前的元素就要直到该元素之前元素的和是否大于0,此时我们可以定义一个dp数组,用来存储之前元素值和;如果该元素之前元素的和大于等于0,那么在dp数组当前位置就存入dp[i-1]+a[i](其中a数组中存储的是输入的若干个元素);如果dp当前元素之前的元素之和小于0,那么就重新构造子数组,dp当前位置存储的是a[i];
这里需要讨论两个特殊情况:
(1)当输入元素第一个就是负数时,那么这个元素就不能包括在子数组当中,因此当前dp数组为dp[0] = 0;
(2)当输入元素都是负数时,那么此时子数组的元素就只能找值最大的那一个负数。
算法实现:
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
//获取数组的长度
Scanner scanner = new Scanner(System.in);
String str = scanner.nextLine();
int len = Integer.parseInt(str);
//定义一个数组用来存储数据
int[] a = new int[len];
//获取数组当中的元素
String str2 = scanner.nextLine();
String[] strs = str2.split(" ");
for (int i=0;i<strs.length;i++){
a[i] = Integer.parseInt(strs[i]);
}
//定义数组来存储累加和
int[] dp = new int[len];
//如果都是负数
boolean isFu = true;
int max1 = Integer.MIN_VALUE;
for (int i = 0;i<a.length;i++){
if (a[i]>=0){
isFu = false;
}else{
//如果是负数则找最大值
max1 = Math.max(max1,a[i]);
}
}
if (isFu){
//表示数组都为负数或0
System.out.println(max1);
}else{
//特殊值:第一位为负数
if (a[0]>=0){
dp[0] = a[0];
}else if (a[0]<0){
//小于0,那么就不记录第一个
dp[0] = 0;
}
for (int i=1;i<dp.length;i++){
if (dp[i-1]+a[i]<=0){
//如果之前数组累加和小于0,不要
dp[i] = 0;
}else if (dp[i-1]+a[i]>0){
dp[i] = dp[i-1]+a[i];
}
}
//得出最大的
int max = Integer.MIN_VALUE;
for (int i=0;i<dp.length;i++){
if (dp[i]>max){
max = dp[i];
}
}
System.out.println(max);
}
}
}