相关介绍:

 求取数组中最大连续子序列和问题,是一个较为“古老”的一个问题。该问题的描述为,给定一个整型数组(当然浮点型也是可以的啦),求取其下标连续的子序列,且其和为该数组的所有子序列和中值为最大的。例如数组A={1, 3, -2, 4, -5},则最大连续子序列和为6,即1+3+(-2)+ 4 = 6。解决该问题的算法有四种,根据其时间复杂度的高低,下面分别为这四种算法做介绍。

第一种:时间复杂度为O(N^3)

 该算法也是最容易想到的,很直观的算法,其算法的思路为,穷举数组中以某个元素为起始元素,以另一个元素为终止元素的元素子序列的和,并记录找出的子序列和最大的那个值

示例代码如下:

/**
* 用于演示O(N^3)的算法
* @param array 用于寻找最大连续子序列和的数组
* @return 最大连续子序列和的值
*/
public int maxSubN3(int[] array)
{
int result=0;
int length=array.length;
//用于控制子序列的起始下标
for(int i=0;i<length;i++)
{
//用于控制子序列的终止下标
for(int j=i;j<length;j++)
{
//用于计算起始下标到终止下标之间的元素的和
int sum=0;
for(int k=i;k<=j;k++)
{
sum+=array[k];
}
result=Math.max(sum, result);
}
}
return result;
}

第二种:时间复杂度为O(N^2)

 该算法通过对上面算法的实现方式进行改进,从而降低了时间复杂度。该算法的思路同上一个的大致相同,但是注意到,每次将终止元素的下标往后移动一位的时候,其子序列和又重新计算了一遍。为此,可以通过保留其上一次从起始元素到终止元素的之间的子序列和的计算结果,来减低时间复杂度。

示例代码如下:

/**
* 用于演示O(N^2)的算法
* @param array 用于寻找最大连续子序列和的数组
* @return 最大连续子序列和的值
*/
public int maxSubN2(int[] array)
{
int length=array.length;
int result=0;
for(int i=0;i<length;i++)
{
int sum=0;
for(int j=i;j<length;j++)
{
sum+=array[j];
result=Math.max(result, sum);
}
}
return result;
}

第三种:时间复杂度为O(NlogN)

 采用分治的思想,将数组划分为两半,最大连续子序列和出现的地方只可能有三种,要么在数组的左半边,要么在数组的右半边,要么横跨了数组的左右半边,同时其必定包含数组左半边的右边界以及数组右半边的左边界

/**
* 用于演示O(NlogN)的算法
* @param array 用于寻找最长子序列的数组
* @return
*/
public int maxSubNlogN(int[] array)
{
return maxSubNlogN(array,0,array.length-1);
}
/**
* 用于递归的那个方法,low和high为数组的左右边界
*/
private int maxSubNlogN(int[] array,int low,int high)
{
//当只剩下一个数组元素的时候,将其直接进行返回
if(low==high)
return Math.max(array[low], 0);
//找到数组中间的分界点
int mid=low+(high-low)/2;
//用于寻找到横跨数组左右半边的那个最长子序列
int lMax=0,rMax=0;
int lSum=0,rSum=0;
//找到包含右边界的左半边的最长子序列
for(int i=mid;i>=low;i--)
{
lSum+=array[i];
lMax=Math.max(lSum, lMax);
}
//找到包含左边界的右半边的最长子序列
for(int i=mid+1;i<high;i++)
{
rSum+=array[i];
rMax=Math.max(rSum, rMax);
}
//返回三种情况中子序列和最大的那个值
return Math.max(maxSubNlogN(array,mid+1,high),Math.max(rMax+lMax, maxSubNlogN(array,low,mid)));
}

第三种:时间复杂度为O(N)

 由分析可知,数组的最大连续子序列中的包含最大连续子序列的开头元素或者末尾元素的任意一个子序列里的元素值之和均为正数。为此,可以在仅需遍历一遍数组的过程中,计算出其最大连续子序列和

示例代码如下:

/**
* 用于演示O(N)的算法
* @param array 用于寻找最长子序列的数组
* @return 最长子序列的值
*/
public int maxSubN(int[] array)
{
int sum=0;
int result=0;
for(int i=0;i<array.length;i++)
{
sum+=array[i];
if(sum>result)
result=sum;
if(sum<0)
sum=0;
}
return result;
}

代码汇总如下:

package other;
/**
* 该类用于演示寻找最长子序列的几种算法
* @author 学徒
*
*/
public class MaxSubLined
{
public static void main(String[] args)
{
int[] array={-2,11,-4,13,-5,2,-5,-3,12,-9};
MaxSubLined max=new MaxSubLined();
System.out.println(max.maxSubN3(array));
System.out.println(max.maxSubN2(array));
System.out.println(max.maxSubNlogN(array));
System.out.println(max.maxSubN(array));
}
/**
* 用于演示O(N^3)的算法
* 算法的思路:
* 穷举数组中以某个元素为起始的,数组中以该元素为起始元素的所有子序列的可能
* 并找出其中子序列和最大的那个值
* @param array 用于寻找最长子序列的数组
* @return 最长子序列的值
*/
public int maxSubN3(int[] array)
{
int result=0;
int length=array.length;
//用于控制子序列的起始下标
for(int i=0;i<length;i++)
{
//用于控制子序列的终止下标
for(int j=i;j<length;j++)
{
//用于计算起始下标到终止下标之间的元素的和
int sum=0;
for(int k=i;k<=j;k++)
{
sum+=array[k];
}
result=Math.max(sum, result);
}
}
return result;
}
/**
* 用于演示O(N^2)的算法
* 算法的思路:
* 穷举数组中以某个元素为起始的,数组中以该元素为起始元素的所有子序列的可能
* 并找出其中子序列和最大的那个值
* @param array 用于寻找最长子序列的数组
* @return 最长子序列的值
*/
public int maxSubN2(int[] array)
{
int length=array.length;
int result=0;
for(int i=0;i<length;i++)
{
int sum=0;
for(int j=i;j<length;j++)
{
sum+=array[j];
result=Math.max(result, sum);
}
}
return result;
}
/**
* 用于演示O(NlogN)的算法
* 算法的思路:
* 采用分治的思想,将数组划分为两半,最长子序列出现的可能只有三种
* 要么在数组的左半边,要么在数组的右半边,要么横跨了数组的左右半边,同时其必定包含
* 数组左半边的右边界以及数组右半边的左边界
* @param array 用于寻找最长子序列的数组
* @return
*/
public int maxSubNlogN(int[] array)
{
return maxSubNlogN(array,0,array.length-1);
}
/**
* 用于递归的那个方法,low和high为数组的左右边界
*/
private int maxSubNlogN(int[] array,int low,int high)
{
//当只剩下一个数组元素的时候,将其直接进行返回
if(low==high)
return Math.max(array[low], 0);
//找到数组中间的分界点
int mid=low+(high-low)/2;
//用于寻找到横跨数组左右半边的那个最长子序列
int lMax=0,rMax=0;
int lSum=0,rSum=0;
//找到包含右边界的左半边的最长子序列
for(int i=mid;i>=low;i--)
{
lSum+=array[i];
lMax=Math.max(lSum, lMax);
}
//找到包含左边界的右半边的最长子序列
for(int i=mid+1;i<high;i++)
{
rSum+=array[i];
rMax=Math.max(rSum, rMax);
}
//返回三种情况中子序列和最大的那个值
return Math.max(maxSubNlogN(array,mid+1,high),Math.max(rMax+lMax, maxSubNlogN(array,low,mid)));
}
/**
* 用于演示O(N)的算法
* 算法的思路:
* 因为最长子序列中的任意一个子序列里的元素值总和均为正数
* 为此,可以在遍历数组的过程中,计算出其最长子序列
* @param array 用于寻找最长子序列的数组
* @return 最长子序列的值
*/
public int maxSubN(int[] array)
{
int sum=0;
int result=0;
for(int i=0;i<array.length;i++)
{
sum+=array[i];
if(sum>result)
result=sum;
if(sum<0)
sum=0;
}
return result;
}
}

回到目录|·(工)·)

K:求取数组中最大连续子序列和的四个算法的更多相关文章

  1. 求一个数组中最小的K个数

    方法1:先对数组进行排序,然后遍历前K个数,此时时间复杂度为O(nlgn); 方法2:维护一个容量为K的最大堆(<算法导论>第6章),然后从第K+1个元素开始遍历,和堆中的最大元素比较,如 ...

  2. python实现给定K个字符数组,从这k个字符数组中任意取一个字符串,按顺序拼接,列出所有可能的字符串组合结果!

    题目描述:给定K个字符数组,从这k个字符数组中任意取一个字符串,按顺序拼接,列出所有可能的字符串组合结果! 样例: input:[["a","b"," ...

  3. 转载——JavaScript学习笔记:取数组中最大值和最小值

    转载自:http://www.w3cplus.com/javascript/calculate-the-max-min-value-from-an-array.html. 取数组中最大值 可以先把思路 ...

  4. JavaScript学习:取数组中最大值和最小值

    在实际业务中有的时候要取出数组中的最大值或最小值.但在数组中并没有提供arr.max()和arr.min()这样的方法.那么是不是可以通过别的方式实现类似这样的方法呢?那么今天我们就来整理取出数组中最 ...

  5. 求出数组中所有数字的和&&弹出层效果

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  6. 黑马基础阶段测试题:定义一个int类型的数组,数组中元素为{5,7,3,9,4}。求出数组中的最小值,并判断最小值是否为偶数,如果是偶数则输出“最小值为偶数”,如果不是偶数则输出“最小值为奇数”。打印如下:

    package com.swift; import java.util.Arrays; public class ArrayTest { public static void main(String[ ...

  7. 《程序员代码面试指南》第七章 位运算 在其他数都出现k 次的数组中找到只出现一次的数

    题目 在其他数都出现k 次的数组中找到只出现一次的数 java 代码 package com.lizhouwei.chapter7; /** * @Description: 在其他数都出现k 次的数组 ...

  8. 如何求出数组中最小(或者最大)的k个数(least k问题)

    输入n个整数,如何求出其中最小的k个数? 解法1. 当然最直观的思路是将数组排序,然后就可以找出其中最小的k个数了,时间复杂度以快速排序为例,是O(nlogn): 解法2. 借助划分(Partitio ...

  9. [LeetCode] Split Array into Consecutive Subsequences 将数组分割成连续子序列

    You are given an integer array sorted in ascending order (may contain duplicates), you need to split ...

随机推荐

  1. 【flask macro】No caller defined

    https://segmentfault.com/q/1010000005352059/a-1020000005352912 先码着 有时间了再换成caller() 先用老方法吧...

  2. php性能优化三(PHP语言本身)

    0.用单引号代替双引号来包含字符串,这样做会更快一些.因为PHP会在双引号包围的字符串中搜寻变量,单引号则不会,注意:只有echo能这么做,它是一种可以把多个字符串当作参数的“函数”(译注:PHP手册 ...

  3. 【微信小程序】——实战开发之和风(含demo)

    微信小程序之和风 序 凑了一把微信小程序的热闹!12月,小程序正式发布,很火,但随之而来的是各种冷水,唱衰之调随处可见.但作为一个小前端,岂能有新技术却弃之不顾之理,更何况是微信出品的?抱着学习和研究 ...

  4. Oracle to_char的用法

    The following are number examples for the to_char function. to_char(1210.73, '9999.9') would return ...

  5. Linux之Ubuntu切换root su -

    当在Ubuntu系统从普通用户切换到root用户时,总是会报错,提示错误信息.这时因为我们还没有给系统中的root用户设置密码,我们给Ubuntu系统中的root用户设置一个密码就可以实现普通用户和管 ...

  6. Great Expectations

    Dear friend, This game is created based on Dicken's Great Expectations. To colorful the contents, I ...

  7. Codeforces Round #555 (Div. 3) C2. Increasing Subsequence (hard version)【模拟】

    一 题面 C2. Increasing Subsequence (hard version) 二 分析 需要思考清楚再写的一个题目,不能一看题目就上手,容易写错. 分以下几种情况: 1 左右两端数都小 ...

  8. dubbo学习笔记:快速搭建

    搭建一个简单的dubbo服务 参考地址: dubbo官网:http://dubbo.apache.org/zh-cn/docs/user/references/registry/zookeeper.h ...

  9. 四、OE 中添加对供应商名称的唯一限制

    最初的思路是利用sql_constraints 来限制重复的供应商名称,但后来想到在OE中供应商.客户乃至员工都隶属于Partner,sql_constrainst实际上是通过限制partner来限制 ...

  10. mono for android 百度map binding项目(转)

    好丫小子之前发布过百度地图android SDK的mono for android绑定dll,许多朋友看过之后说想理解是怎么绑定的,现我把绑定的代码发出来. 针对2.1.2版本百度地图android ...