/**数组
1)将待求解的问题分解为若干个子问题(即:将求解的过程分为若干阶段),按顺序求解子问题,前一子问题的解,为后一子问题的求解提供了有用的信息;
2)在求解任一子问题时,列出可能的局部解,经过决策保留那些有可能达到最优的局部解,丢弃其它的局部解;
3)依次解决各子问题,最后一个子问题的解就是初始问题的解。
*/code
public class DP { /** * 暴力求解 * * 时间复杂度:O(N^2) */ public static int maxSubSumByEnum(int[] array) { int maxSum = 0; int begin = 0; int end = 0; /** * 1)第i次循环结束后能够找到:以第i个元素为起点的连续子序列的最大值。 * 2)i表示序列的起点,j表示序列的终点。 * 3)每一次循环中将终点不断向后移动:每次向后移动一位而且计算当前序列的和,循环结束后,咱们就能够获得本次循环中子序列和最大的值。 */ for (int i = 0; i < array.length; i++) { // int tempSum = 0; for (int j = i; j < array.length; j++) { tempSum += array[j]; if (tempSum > maxSum) { maxSum = tempSum; begin = i; end = j; } } } System.out.println("begin:" + begin + " end:" + end); return maxSum; } /** * 动态规划 * * 时间复杂度:O(N) * * 要点: * 1)若当前阶段中连续子序列的和小于0,则进入下一阶段,同时肯定下一阶段的起点并将下一阶段的和初始化为0。 * 2)只有当前阶段的总和大于历史最大总和时,才会去更新数组中最大连续子序列的起点和终点。 */ public static int maxSubSumByDP(int[] array) { int maxSum = 0; // 数组中,最大连续子序列的和 int begin = 0; // 数组中,最大连续子序列的起点 int end = 0; // 数组中,最大连续子序列的终点 int tempSum = 0; // 当前阶段中,连续子序列的和 int tempBegin = 0; // 当前阶段中,连续子序列的起点 for (int i = 0; i < array.length; i++) { tempSum += array[i]; if (tempSum < 0) { // 若当前阶段中连续子序列的和小于0,则进入下一阶段 tempSum = 0; // 下一阶段的和进行归零处理 tempBegin = i + 1; // 下一阶段的起点 } else if (tempSum > maxSum) { // 若当前阶段的总和大于历史最大总和,则更新数组中最大连续子序列的起点和终点。 maxSum = tempSum; begin = tempBegin; end = i; } } System.out.println("begin:" + begin + " end:" + end); return maxSum; } public static void main(String[] args) { int[] array = {1, -3, 7, 8, -4, 10, -19, 11}; int dpMax = maxSubSumByDP(array); System.out.println(dpMax); int enumMax = maxSubSumByEnum(array); System.out.println(enumMax); }
}class