HDOJ链接 http://acm.hdu.edu.cn/showproblem.php?pid=1003 不了解题目的朋友可以先看一下题目,在这里就不再详细介绍了。(文章内容和解题思路不完全相同,方法一、二、三、四没有对sequence 全为负数的情况进行考虑,就不再对代码进行更新了,如果需要可看1003解题代码,最下面。)

Given a sequence a[1],a[2],a[3]......a[n], your job is to calculate the max sum of a sub-sequence.

For example, given (6,-1,5,4,-7), the max sum in this sequence is 6 + (-1) + 5 + 4 = 14.

下面就直接进行分析:

 方法一:暴力破解,时间复杂度:O(n^3)

  对所有情况的子串进行计算,然后求出和最大的子串。这个就不详细解释了看代码就能明白。

private void test01() {
int maxValue = 0;
for (int i = 0; i < array.length; i++) {// 第一次循环
for (int j = i; j < array.length; j++) {// 第二次循环
int thisMaxValue = 0; // 这里置零
for (int k = j; k < array.length; k++) {// 开始新的循环计算thisMaxValue
thisMaxValue += array[k];
}
if (thisMaxValue > maxValue) {
maxValue = thisMaxValue;
}
}
}
System.out.println(maxValue);
}

 方法二:还是暴力破解,时间复杂度:O(n^2) 。需要注意的是和方法一的区别。

public void test02() {
int maxValue = 0;
for (int i = 0; i < array.length; i++) {// 第一次循环
int thisMaxValue = 0;
for (int j = i; j < array.length; j++) {// 第二次循环
thisMaxValue += array[j]; // 这里没有置零,利用了上个thisMaxValue数值
if (thisMaxValue > maxValue) {
maxValue = thisMaxValue;
}
}
}
System.out.println(maxValue);
}

  区别:方法一每次都是对子串全部循环一遍,而方法二,利用了第二层循环,不再对子串进行全部循环。

 方法三:分治算法,递归求解。时间复杂度:O(nlogn)

public void test03() {
System.out.println(start(array, 0, array.length / 2, array.length - 1));
}
//递归方法
private int start(int[] array, int left, int mid, int right) {
if (left == right) {
return array[left];
}
int leftMaxValue = start(array, left, (left + mid) / 2, mid);// 递归求左子串的最大值
int rightMaxValue = start(array, mid + 1, (mid + right) / 2, right);// 递归求右子串的最大值
/**
开始计算跨两边的最大子序列
       toLeftMaxValue <—— MaxSum(mid to left)
     toRightMaxValue<—— MaxSum(mid to right)
       midMaxValue = toLeftMaxValue +toRightMaxValue;
**/ int toLeftMaxValue = 0;
int tempMaxValue = 0;
for (int i = mid; i >= 0; i--) {
tempMaxValue += array[i];
if (tempMaxValue > toLeftMaxValue) {
toLeftMaxValue = tempMaxValue;
}
} tempMaxValue = 0;
int toRightMaxValue = 0;
for (int i = mid + 1; i <= right; i++) {
tempMaxValue += array[i];
if (tempMaxValue > toRightMaxValue) {
toRightMaxValue = tempMaxValue;
}
}
//计算出跨左右两边的最大子串和
int midMaxValue = toRightMaxValue + toLeftMaxValue; //返回本层循环的最大子串和
return Math.max(Math.max(leftMaxValue, midMaxValue), rightMaxValue);
}

需要好好考虑的是为何在计算夸两边最大子串和的时候需要 toRightMaxValue + toLeftMaxValue,考虑明白这个问题,方法三也就明白了。因为 toLeftMaxValue 的子串和 toRightMaxValue 的子串是连接着的,其节点就是mid,所以两者完全可以进行相加以求出跨两边的最大子串和。

  方法四:遍历累积。时间复杂度:O(n)。

    public void test04() {
int maxValue = 0;
int thisMaxValue = 0;
for (int i = 0; i < array.length; i++) {
thisMaxValue += array[i];
if (thisMaxValue > 0) {
maxValue = thisMaxValue > maxValue ? thisMaxValue : maxValue;
} else { // 当子串不大于零的时候,子串断裂,开始新的子串。
thisMaxValue = 0;
}
}
System.out.println(maxValue);
}

  不再解释。

  后面还有两种方法没有实现。有兴趣的可以参考这里:http://blog.csdn.net/samjustin1/article/details/52043369

1003的代码更新上:

import java.util.Scanner;

public class Main {

    static int maxValue;

    public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int num = in.nextInt();
int tip = 1;
while (in.hasNextInt()) {
String[] datas = in.nextLine().split(" ");
if (!"".equals(datas[0])) {
getMaxValue(tip++, datas);
if (tip > num) {
break;
}
System.out.println();
}
} } private static void getMaxValue(int num, String[] array) {
boolean isAllNegative = true, isFirstPositive = true;//是否都为负数 是否是第一个正数
int maxValue = 0; //最终的最大值
int start = 1, end = 1, thisStart = 1, thisEnd = 1;//最终子串的起始为止 最终的子串结束为止 本次循环的起始位置 本次循环的结束位置
int thisMaxValue = 0; //本次循环的最大值
for (int i = 1; i < array.length; i++) {
if (isAllNegative) {//如果该子串都是负数则不进行累加,负数越加越小
thisMaxValue = Integer.parseInt(array[i]);
} else {//如果包含正数则进行累加
thisMaxValue += Integer.parseInt(array[i]);
}
if (thisMaxValue > 0) {//本次循环的子串大于零则需要和前面的子串进行相加
if (thisMaxValue > maxValue) {//循环子串大于最大值则把本次循环的结果进行保存
isAllNegative = false; //此时,整个串必定包含正数,所以改变标识符
maxValue = thisMaxValue;
thisEnd = i;
if (isFirstPositive) {
thisStart = i;
isFirstPositive = false;
}
start = thisStart;
end = thisEnd;
}
} else if (thisMaxValue < 0) {//本次循环结果小于零时
if (isAllNegative) {//都是负数则对maxValue、start和end进行更新
if (i == 1) {
maxValue = Integer.parseInt(array[i]);
}
if (maxValue < Integer.parseInt(array[i])) {
start = i;
end = i;
maxValue = Integer.parseInt(array[i]);
}
} else {//此时新的子串诞生,记录下本子串的起始位置。
thisMaxValue = 0;
thisStart = i + 1;
}
}
}
System.out.println("Case " + num + ":");
System.out.println(maxValue + " " + start + " " + end);
}
}

ACM—最大连续子序列(HDOJ1003)的更多相关文章

  1. 【ACM】 1231 最大连续子序列

    [1231 最大连续子序列 ** Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) To ...

  2. DP专题训练之HDU 1231 最大连续子序列

    Description 给定K个整数的序列{ N1, N2, ..., NK },其任意连续子序列可表示为{ Ni, Ni+1, ..., Nj },其中 1 <= i <= j < ...

  3. HDU-1231 简单dp,连续子序列最大和,水

    1.HDU-1231 2.链接:http://acm.hdu.edu.cn/showproblem.php?pid=1231 3.总结:水 题意:连续子序列最大和 #include<iostre ...

  4. [HDOJ1231]最大连续子序列

    混了好几个地方的博客,还是觉得博客园比较靠谱,于是决定在这里安家落户了.本人本科生一个,希望各位巨巨多多指教~ Hello World! 单独一个象征性的问候实在是太low了,还是决定来点实质性的.. ...

  5. HDU 1231 最大连续子序列:水dp

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1231 题意: 给你一个整数序列,求连续子序列元素之和最大,并输出该序列的首尾元素(若不唯一,输出首坐标 ...

  6. 最大连续子序列 -- hdu -- 1231

    http://acm.hdu.edu.cn/showproblem.php?pid=1231 最大连续子序列 Time Limit: 2000/1000 MS (Java/Others)    Mem ...

  7. ACM-DP之最大连续子序列——hdu1231

    ***************************************转载请注明出处:http://blog.csdn.net/lttree************************** ...

  8. TOJ 5065: 最长连续子序列

    5065: 最长连续子序列   Time Limit(Common/Java):1000MS/3000MS     Memory Limit:65536KByteTotal Submit: 140   ...

  9. 题解报告:hdu1231最大连续子序列

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1231 Problem Description 给定K个整数的序列{ N1, N2, ..., NK } ...

随机推荐

  1. jQuery 追加元素的方法如append、prepend、before

    1.jQuery append() 方法 jQuery append() 方法在被选元素的结尾插入内容. 实例 复制代码代码如下: $("p").append("Some ...

  2. 对自己的文件使用keystore签名

    keytool 对jar包签名步骤: 1.将程序打成jar包. 2.生成keystore数字证书keytool -genkey -keystore xxx.keystore -alias xxx -v ...

  3. 【python】浅谈包

    python中的包可以理解为模块的集合.每个包也既可以为单包也可以有多个小包组成. Python中的package定义很简单,其层次结构与目录的层次结构相同,但是每个package必须包含一个__in ...

  4. Python基础教程【读书笔记】 - 2016/7/31

    希望通过博客园持续的更新,分享和记录Python基础知识到高级应用的点点滴滴! 第十波:第10章  充电时刻 Python语言的核心非常强大,同时还提供了更多值得一试的工具.Python的标准安装包括 ...

  5. 修改tcp内核参数:somaxconn

    修改somaxconn 该内核参数默认值一般是128(定义了系统中每一个端口最大的监听队列的长度),对于负载很大的服务程序来说大大的不够.一般会将它修改为2048或者更大. echo 2048 > ...

  6. MySQL存储引擎MyISAM与InnoDB的优劣

    使用MySQL当然会接触到MySQL的存储引擎,在新建数据库和新建数据表的时候都会看到. MySQL默认的存储引擎是MyISAM,其他常用的就是InnoDB了. 至于到底用哪种存储引擎比较好?这个问题 ...

  7. bzoj3007: 拯救小云公主

    Description     英雄又即将踏上拯救公主的道路……     这次的拯救目标是——爱和正义的小云公主.     英雄来到boss的洞穴门口,他一下子就懵了,因为面前不只是一只boss,而是 ...

  8. java获取url中的参数

    获取地址栏中的url中的userName的值 String userName=new String(request.getParameter("userName")); 获取中文的 ...

  9. Configure Puppet Master with Passenger and Apache on Centos

    What is Passenger? Passenger (AKA mod_rails or mod_rack) is an Apache 2.x module which lets you run ...

  10. Redis作者谈Redis应用场景(转)

    毫无疑问,Redis开创了一种新的数据存储思路,使用Redis,我们不用在面对功能单调的数据库时,把精力放在如何把大象放进冰箱这样的问题上,而是利用Redis灵活多变的数据结构和数据操作,为不同的大象 ...