1、问题:
有一个整数数组arr,请找出一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。子数组是数组中的一个连续部分。
2、动态规划解题思路:(实例解说)
以下以数组 arr[100]={5,7,-15,13,-3,6} 为例
⭐核心思路:
以数组中的每一个数字作为一个子数组的最后一个数字,向前遍历求和。如果此数字的前一个子数组和为负,则以这个数字为最后一个数字的子数组的最大和为此数字本身;如果此数字之前的子数组和为正,则以这个数字为最后一个数字的子数组和最大和为此数字本身加上前一个的子数组和。每做一次子数组求和,就与前面出现的最大和作比较,如果此子数组和大于前面的最大子数组和,就将赋值给最大值。这段文字有点绕,我们直接看下面的例子就明白了。
⭐过程分析:
以一个表格的形式表示动态过程。
1、梳理动态过程及其每个变量的含义⭐⭐
- 第一行的表示实例 arr[n] 的值;
- 第一列表示以每一个 arr[i] 中的值作为一个子数组的最后一个数;
- 新建一个 dp[i] 来存储以 arr[i] 作为子数组结尾数字的子数组的最大和,也就是此表格的白色部分每行最右边的数字,例如dp[0]=arr[0]=5; dp[1]=12;dp[2]=-3; dp[3]=13……
- 表中标红的数字表示计算到此处的时候,子数组和中最大的值,在后文编程中记为 max;
arr[n] | 5 | 7 | -15 | 13 | -3 | 6 |
---|---|---|---|---|---|---|
5 | 5 | |||||
7 | 5 | 12 | ||||
-15 | 5 | 12 | -3 | |||
2 | 5 | 12 | -3 | 13 | ||
-3 | 5 | 12 | -3 | 13 | 10 | |
6 | 5 | 12 | -3 | 13 | 10 | 16 |
2、关系式推导
⭐⭐⭐得出关系式表达式:
- 当dp[i-1]<0时:dp[0]=arr[0];
- 当dp[i-1]>0时:dp[i]=arr[i]+dp[i-1]
3、代码展示
package Array;
import java.util.Scanner;
public class LargestSubarraySum{
public static int method(int[] arr){
int max=Integer.MIN_VALUE;
int[] dp = new int[arr.length];//dp[]用于存储以arr[i]结尾的子数组最大和
dp[0] = arr[0];
for(int i=1; i<arr.length; i++) {
if(dp[i-1] > 0) {
dp[i] = arr[i] + dp[i-1];
}else {
dp[i] = arr[i];
}
max=Math.max(max,dp[i]);
}
return max;
}
public static void main(String[] args) {
System.out.println("请输入您想要求子数组最大和的数据:");
Scanner sc = new Scanner(System.in);
int number = Integer.parseInt(sc.next());
int[] num = new int[number];
for(int i=0; i<number; i++) {
num[i] = sc.nextInt();
}
System.out.println("此数据的最大子数组和为:");
System.out.println(method(num));
}
}
运行结果: