
本文旨在提供一个清晰易懂的Java教程,用于寻找列表中元素之和最大的连续子序列,并在存在多个和相同的子序列时,返回长度最长的那个。我们将详细解释算法逻辑,并提供可直接运行的代码示例,帮助读者理解并应用该算法。
在编程中,经常会遇到需要寻找数组或列表中特定子序列的问题。其中一个经典问题是:如何找到一个连续子序列,使其元素之和最大?更进一步,如果存在多个和相同的最大子序列,我们又该如何选择长度最长的那个呢?本文将提供一个Java实现的解决方案。
算法思路
解决这个问题的关键在于使用 Kadane 算法的变体。Kadane 算法用于查找数组中最大和的连续子数组。为了满足“长度最长”的条件,我们需要在找到相同和的子序列时,比较它们的长度,并保留长度更长的那个。
具体步骤如下:
立即学习“Java免费学习笔记(深入)”;
-
初始化:
- maxSumStartIndex: 最大和子序列的起始索引。
- maxSumLastIndex: 最大和子序列的结束索引。
- maxSum: 最大和。
- maxSumLength: 最大和子序列的长度。
- lastSumStartIndex: 当前正在计算的子序列的起始索引。
- lastSum: 当前正在计算的子序列的和。
- 遍历列表: 从列表的第二个元素开始遍历。
- 更新当前子序列的和: lastSum += list.get(i)。
- 如果当前子序列的和小于当前元素: 说明从当前元素开始新的子序列可能得到更大的和。因此,重置 lastSum 为当前元素,并更新 lastSumStartIndex。
- 如果当前子序列的和大于最大和: 更新 maxSumStartIndex,maxSumLastIndex,maxSumLength 和 maxSum。
- 如果当前子序列的和等于最大和: 比较当前子序列的长度和 maxSumLength。如果当前子序列更长,则更新 maxSumStartIndex,maxSumLastIndex 和 maxSumLength。
- 遍历结束后: maxSumStartIndex 和 maxSumLastIndex 指向的就是最大和且长度最长的连续子序列的起始和结束索引。
Java 代码示例
import java.util.ArrayList;
import java.util.List;
public class MaxSumSubsequence {
public static void main(String[] args) {
List list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(-5);
list.add(6);
list.add(-3);
list.add(-13434);
list.add(99);
list.add(99);
list.add(-444);
list.add(-7444);
list.add(100);
list.add(90);
list.add(8);
if (list == null || list.isEmpty()) {
System.out.println("empty array");
return;
}
int maxSumStartIndex = 0;
int maxSumLastIndex = 0;
int maxSum = list.get(0);
int maxSumLength = 1; // 初始长度为1
int lastSumStartIndex = 0;
int lastSum = list.get(0);
for (int i = 1; i < list.size(); i++) {
lastSum += list.get(i);
if (lastSum < list.get(i)) {
lastSum = list.get(i);
lastSumStartIndex = i;
}
if (maxSum < lastSum) {
maxSumStartIndex = lastSumStartIndex;
maxSumLastIndex = i;
maxSumLength = maxSumLastIndex - maxSumStartIndex + 1;
maxSum = lastSum;
} else if (maxSum == lastSum) {
if (i - lastSumStartIndex + 1 > maxSumLength) {
maxSumStartIndex = lastSumStartIndex;
maxSumLastIndex = i;
maxSumLength = i - lastSumStartIndex + 1;
}
}
}
System.out.println("Sum( arr[" + maxSumStartIndex + "] .. arr[" + maxSumLastIndex + "] ) = " + maxSum);
System.out.print("Subsequence: ");
for (int i = maxSumStartIndex; i <= maxSumLastIndex; i++) {
System.out.print(list.get(i) + " ");
}
System.out.println();
}
} 代码解释
- 初始化: 初始化变量以跟踪最大和、起始索引、结束索引和长度。
- 循环: 遍历列表中的每个元素。
- Kadane算法: 使用 Kadane 算法来计算当前子序列的和。
- 长度比较: 如果找到具有相同最大和的子序列,则比较它们的长度并选择最长的子序列。
- 输出: 打印最大和以及对应的子序列。
注意事项
- 空列表处理: 在代码的开头,检查列表是否为空。如果为空,则输出一条消息并退出程序,避免空指针异常。
- 负数处理: 该算法可以正确处理包含负数的列表。如果所有元素都是负数,则最大和将是列表中最大的负数(即绝对值最小的负数)。
- 时间复杂度: 该算法的时间复杂度为 O(n),其中 n 是列表的长度。这是因为我们只需要遍历列表一次。
- 空间复杂度: 该算法的空间复杂度为 O(1),因为我们只使用了几个额外的变量来存储最大和、索引和长度。
总结
本文提供了一个使用Java实现的寻找最大和的连续子序列,并且在存在多个和相同的子序列时,返回长度最长的那个的解决方案。该算法基于 Kadane 算法,并通过添加长度比较逻辑来满足特定的需求。代码示例清晰易懂,并包含了必要的注释,方便读者理解和应用。希望本文能够帮助读者更好地理解和解决相关问题。










