Maximum Subsequence Sum

来源:互联网 发布:数据库防护产品 编辑:程序博客网 时间:2024/06/12 15:13

最大子列和问题

import java.util.Scanner;public class Main {    public static void main(String[] args) {        Scanner sc = new Scanner(System.in);        int inputNum = Integer.parseInt(sc.nextLine());        String inputStr = sc.nextLine();        String[] strArray = inputStr.split(" ");        int array[] = new int[inputNum];        for (int i = 0; i < inputNum; i++) {            array[i] = Integer.parseInt(strArray[i]);        }        System.out.println(maxSubSeqSum(array));    }    //方法一,记录开始值和结束值之间的距离    public static String maxSubSeqSum(int[] array) {        int thisSum = 0; // 序列和累加变量        int maxSum = 0; // 最大和        boolean flag = true; // 判断是否需要修改最大子序列和的开始值。true:需要修改,false:不需要改        boolean allNeflag = true; // 判断输入项是否都为负数        int startNum = array[0]; // 最大子序列开始值        int endNum = array[0];// 最大子序列结束值        // 开始循环遍历序列,找出最大序列总、开始项和结束项        // j表示开始项到结束项之间的长度        for (int i = 0, j = 0; i < array.length; i++) {            thisSum += array[i];            // 判断当前累加和是否>最大累加值,需要特殊处理以0开始的序列            if (thisSum > maxSum || (maxSum == 0 && thisSum == 0)) {                allNeflag = false; // 只要有一项>=0,就置allNeflag为false                // 判断是否需要修改当前开始项                if (flag) {                    // 开始项的值需要从当前项i向前移动j个单位长度                    startNum = array[i - j];                    flag = false; // 移动完后将flag置为false,将修改开始值的开关关掉                }                maxSum = thisSum; // 将最大值指向当前累加值。                endNum = array[i]; // 记录结束项的值            } else if (thisSum < 0) {                // 如果当前累加的值 < 0,将当前累加和置为0,并且将修改开始值的开关打开                thisSum = 0;                flag = true;                j = 0; // 将移动距离置为0            } else {                // thisSum>0,需要将移动距离+1                j++;            }        }        // 输出        if (allNeflag) {            // 如果都为负数,返回: 0 数组[开始项] 数组[结束项]            return 0 + " " + array[0] + " " + array[array.length - 1];        } else {            // 返回 最大子序列和 开始项值 结束项值            return maxSum + " " + startNum + " " + endNum;        }    }    //方法二:通过数组记录位置,从数组末尾向前遍历确定连续子列的开始项和结束项。    public static String maxSubSeqSum(int[] array) {        int thisSum = 0;        int maxSum = 0;        int j = 0;        int endNum = 0;        int[] startEndList = new int[array.length];        for (int i = 0; i < array.length; i++) {            thisSum += array[i];            if (thisSum > maxSum || (maxSum == 0 && thisSum == 0)) {                startEndList[j] = i;                endNum = j;                j++;                maxSum = thisSum;            } else if (thisSum < 0) {                thisSum = 0;            } else {                startEndList[j] = i;                j++;            }        }        if (j > 0) {            int startPos = startEndList[endNum];            for (int i = endNum; i >= 1; i--) {                if ((startEndList[i] - startEndList[i - 1]) == 1) {                    startPos = startEndList[i - 1];                } else {                    startPos = startEndList[i];                }            }            return maxSum + " " + array[startPos] + " " + array[startEndList[endNum]];        } else {            return 0 + " " + array[0] + " " + array[array.length - 1];        }    }}