算法_02
来源:互联网 发布:淘宝网显示不了图片 编辑:程序博客网 时间:2024/06/07 00:16
- 最大连续子数组
给定一个数组A[0,1,….,n1],求A的连续子数组,使得该子数组的和最大
例如:
数组:1,-2,3,10,-4,7,2,-5
package day7_20;/** * Created by 朱博文 on 2017/7/20. * 最大连续子数组 * 给定一个数组A[0,1,....,n1],求A的连续子数组,使得该子数组的和最大 * 例如: * 数组:1,-2,3,10,-4,7,2,-5 */public class Demo_01 { //暴力法 /** * 直接求解A[i,...j]的值; * 0<=i<n * i<=j<n * i,i+1,...,j-1,j的最大长度为n * 因此:时间复杂度O(n^3) */ public static int MaxSubArray(int[] A, int n) { int maxSum = A[0]; int currSum = 0; for (int i = 0; i < n; i++) { for (int j = i; j < n; j++) { for (int k = i; k < j; k++) { currSum += A[k]; if (currSum > maxSum) { maxSum = currSum; } } } } return maxSum; } //分治法 /** * 把数组从中间分开,那么最大子数组要么完全在左半边,要么完全在右半边数组,要么跨立在分界点上。 * 完全在左数组,右数组递归解决 * 跨立在分界点上:实际上是做数组的最大后缀和有数组的最大前缀的和。因为,从分界点向前扫,向后扫即可。 * 算法的递推关系:T(n) = 2*T(n/2)+c*n,c为常数 * 若n=2^k,则有:T(n):T(n) = 2*T(n/2)+c*n * = 2*(2*T(n/4)+c*n/2)+c*n = 4T(n/4)+2c*n * = 4*(2*T(n/8)+c*n/4)+2c*n = 8T(n/8)+3c*n * = 4*(2*T(n/16)+c*n/8)+3c*n = 16T(n/16)+4c*n * = ..... * =2^k*T(1)+kc*n=an+c*nlog2n * 若2^k<n<2^(k+1),则T(2^k) < T(n) <T(2^(k+1)) * 所以得:T(n) = O(nlogn) **/ public static int MaxAddSub(int[] a, int from, int to) { if (from == to) { //递归出口 return a[from]; } int middle = (from + to) / 2; int m1 = MaxAddSub(a, from, middle); //求一下前一段部分最大的子数组 int m2 = MaxAddSub(a, middle + 1, to); //求一下后一段部分最大的子数组 int i, left = a[middle], now = a[middle]; for (i = middle - 1; i >= from; --i) { //数组左半部分的最大后缀和 now += a[i]; left = Math.max(now, left); } int right = a[middle + 1]; now = a[middle - 1]; for (i = middle + 2; i <= to; ++i) { //数组右半部分的最大前缀和 now += a[i]; right = Math.max(now, right); } int m3 = left + right; //中间部分的数组的最大值 return Math.max(Math.max(m1, m2), m3); //比较是哪一个值大 } //分析法(逻辑推理的算法应用) /** * 前缀和p[i] = a[0] + a[1] .... +a[i] * s[i,j] = p[j] - p[i-1](定义p[-1] = 0) * 算法过程 * 1.求i前缀p[i] * 遍历i:0<=i<=n-1 * p[i] = p[i-1]+a[i] * 2.计算p[i]-p[j] * 遍历i: 0<=i<=n-1,求最小值m * m的初值取0(p[-1]=0),然后遍历p[0...i-1],更新m * p[i]-m即为以a[i]结尾的数组中最大的子数组 * 3.在第2步中,可顺手记录p[i]-m的最大值。 * 为什么 * 1,2步都是线性的,时间复杂度O(n)。 */ //动态规划法 /** * 进一步分析 * 记S[i]为以A[i]结尾的数组中最大的子数组 * 则:S[i+1] = max(S[i]+A[i+1],A[i+1]) * S[0]=A[0] * 遍历i:0<=i<=n-1 * 动态规划:最优子问题 * 时间复杂度:O(n) */ public static int MaxMath(int[] a) { int result = a[0]; int sum = a[0]; for (int i = 0; i < a.length; i++) { if (sum > 0) { sum += a[i]; } else { sum = a[i]; } if (sum > result) { result = sum; } } return result; } //在线法 /** * 理解这个算法的关键是:使用thisSum来计算当前连续子数组的和 * 如果thisSum小于0,那么无论后面再加上什么数字都只会让子数组变小 * 所以抛弃当前子数组,重新开始计算子数组的值 */ public static int MaxOnline(int[] a) { int sum = 0;//记录子数组的和 int thisSum = 0; for (int i = 0; i < a.length; i++) { thisSum += a[i]; if (thisSum > sum) { sum = thisSum; } else if (thisSum < 0) { thisSum = 0; } } return sum; }}
阅读全文
0 0
- 算法_02
- 【算法杂谈_02】树链剖分
- 算法复习之递归算法_02
- 黑马程序员_浅谈递归算法_02
- 算法题型的个人练习_02
- Dijkstra算法以及java实现_02(代码部分)
- 20170219C++项目班02_02递归下降算法/解析器/Scanner实现
- 03_02.cs
- 单片机C51学习心得_02
- Java线程_02
- Matlab入门_02
- JS高级程序设计_02
- 【新技术_02】枚举
- DB2 基本命令_02
- 数据结构_排序_02
- 02_02.常见标签
- Js_基础知识学习_02
- c#初学_02
- C++中的 菱形继承
- L1-015. 跟奥巴马一起画方块
- 基于集群的单点登录(SSO)系统设计
- 音频算法学习和应用谱图
- java oracle 查询一个月有多少天
- 算法_02
- 线性变换的矩阵为什么要强调在这组基下?
- Andoird屏幕适配
- 创建多层文件夹
- 解决表单重复提交的问题
- javascript-委托事件(事件代理)
- js 函数的参数、调用 代码笔记
- Java多线程(7)——ExecutorService 的理解与使用
- jQuery dialog对话框