1.问题
输入一个整形数组,数组中的值有正整数也有负整数,数组中连续的一个或多个整数构成一个子数组,子数组的各个整数的和称为子数组的和,求最大的子数组的和,并给出该子数组,要求时间复杂度是O(n)。
2.分析
设输入数组为a,设置一个数组b,b的各个元素均初始化为0,b[0]取a[0]和0中最大的一个值,然后b[i]取b[i-1]+a[i],a[i],0中比较大的值,思想就是如果a[i]加上前面的数的和还小于本身的话,说明前面的数是负数,那么前面的数的和就不该加进来,但如果a[i]比0还小,前面已经小于0了,a[i]也不能加进最长子数组。
3.代码
package array;
import java.util.Arrays;
import java.util.Scanner;
/**
* 输入一个整形数组,数组中的值有正整数也有负整数,
* 数组中连续的一个或多个整数构成一个子数组,子数组的各个整数的和称为子数组的和,
* 求最大的子数组的和,并给出该子数组,要求时间复杂度是O(n)。
* */
public class LongestArray {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int n;//数组的长度
n = in.nextInt();
int[] a = new int[n];
for (int i = 0; i < a.length; i++) {
a[i] = in.nextInt();
}
int[] b = new int[n];//用来存储最大子数组的和
b[0] = Math.max(a[0]+b[0], b[0]);
for (int i = 1; i < n; i++) {
b[i] = Math.max(b[i-1]+a[i], a[i]);
b[i] = Math.max(b[i],0);
}
Arrays.sort(b);
System.out.println(b[n-1]);
}
}
4.运行结果
6
-8 5 2 -9 2 3 -8
7
-8 5 2 -9 2 3 -8
7
4.对于二维数组求其子阵的最大和
采用降维的思想,首先从第一行开始,求第一行的最大子数组和,然后将第一行和第二行相应列的元素加起来,成为一维数组,继续求最大子数组的和,直到第一行加到最后一行;然后从第二行开始,求第二行的最大子数组的和,然后将第二行和第三行相应列的元素加起来,成为一维数组,继续求最大子数组的和,直到第二行加到最后一行……
package dynamic.planning;
import java.util.Scanner;
/**
* 输入一个二维矩阵,找出其中最大的子长方形矩阵的和
* 动态规划
* 想想一维数组求最大子数组的和的动态规划
* 将二维数组转化为一维数组即可
* 转化的方式就是将每一行相应列上的值相加
* @author admin
*
*/
public class ToTheMax {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int n = in.nextInt();//输入n*n矩阵
int[][] a = new int[n+1][n+1];
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
a[i][j] = in.nextInt();
}
}
int max = 0;
for (int i = 1; i <= n; i++) {//从第几行开始
int[] b = new int[n+1];
for (int j = i; j <= n; j++) {//从第i行到最后一行
int[] sum = new int[n+1];//用来存储到第i列的最大值
for (int k = 1; k <= n; k++) {
b[k] += a[j][k];
if(sum[k-1]>0){
sum[k] = sum[k-1] + b[k];
}else{
sum[k] = b[k];
}
if(max<sum[k]){//每次找出当前的最大值
max = sum[k];
}
}
}
}
System.out.println(max);
}
}