题目说明
给定一整数序列A1,A2,A3,…,An(其间可能存在负数),求A1到An的一个子序列Ai-Aj,使得Ai~Aj的和最大,并输出子序列的内容。
代码体现
public class MaxSub {
public static void main(String[] args) {
int[] nums = {-4, -2, 1, 4};
method_1(nums);
method_2(nums);
}
//方法一:暴力破解
private static void method_1(int[] nums) {
int step = 1;//进行参与求和的元素个数
int maxSum = nums[0];//默认最大值为第一个元素
int start = 0;//当前和最大子序列的起始下标
int end = 0;//当前和最大子序列的最终下标
List<Integer> subList = new ArrayList<>();//用来存放最终的子序列内容
while (step <= nums.length) {
for (int i = 0; i <= nums.length - step; i++) {
int tempSum = nums[i];
for (int j = i + 1; j < i + step; j++) {
tempSum += nums[j];
}
if (tempSum >= maxSum) {
start = i;
end = i + step - 1;//因为前一个元素已经算进去了,所以这里再减去
maxSum = tempSum;
}
}
step++;//将进行求和的元素个数++
}
for (int i = start; i <= end; i++) {
subList.add(nums[i]);
}
System.out.println("和最大为 = " + maxSum);
System.out.println("其子序列为:" + subList);
}
//方法二:动态规划
private static void method_2(int[] nums) {
int max = nums[0];//默认第一个元素最大
//以第i个元素结尾的和最大的子序列的和,eg:sums[1]以角标为1的元素结尾的最大子序列的和
int[] sums = new int[nums.length];
sums[0] = nums[0];
int[] starts = new int[nums.length];//starts数组的最后一个元素即为子序列的起始位
int end = 0;//子序列的结束位
for (int i = 1; i < nums.length; i++) {
if (sums[i - 1] > 0) { //判断前面的子序列和是否大于0
sums[i] = sums[i - 1] + nums[i];
starts[i] = starts[i - 1];
} else {
sums[i] = nums[i];
starts[i] = i;
}
if (sums[i] > max) {
max = sums[i];
end = i;
}
}
System.out.println("max = " + max + ";start = " + starts[end] + ";end = " + end);
}
}