[算法学习笔记]分治法——最大子序列和问题
来源:互联网 发布:淘宝客服工作好不好干 编辑:程序博客网 时间:2024/05/29 11:45
何为分治法?
在上一篇文章中讲到归并排序就有提到过分治法,这里在重复一次:
分治法
分治法采用了递归的结构,将原问题分成几个规模较小但是类似于原问题的子问题, 通过递归的方式再来求解这些小问题,然后将子问题的解合并来建立原问题的解,分治法在每成递归时都有三个步骤:
- 分解: 将原问题分解成若干个小问题,这些子问题是原问题的规模较小的实例
- 解决: 解决这些子问题,通过递归的方式求解子问题,直到自问题的规模足够小,可以直接求解
- 合并: 将这些子问题的解合并成原问题的解
最大子序列和问题
比如说有一个数组:
4 , -3, 5, -2, -1, -1, 2, 6, -2
对于这样一个数组,它的最大子序列和为11(从第一个元素到第七个)。
对于任意一个栗子,可以发现最大子序列和只有三种情况:
- 出现在数组的左半部分
- 出现在数组的右半部分
- 出现在数组的中间部分,横跨左右两部分
(这不是废话么=_=)
而且对于左半部分或者右半部分,上述结论也成立,利用这特性,可以写出相应的递归,递归结束的条件是当只有一个元素时,判断这个元素是否大于零,大于零便返回这个数,否则返回零。
然后求出左边最大值,右边最大值和横跨两边的最大值,返回这三个值中的最大值
c语言代码如下:
#include <stdio.h>#include <stdlib.h>#include <time.h>#define MAX_N 20int max3(int, int, int);int maxSubArrayAns(int []);int maxSubArray(int [], int, int);int main(){ int nums[MAX_N]; int i; srand(time(0)); printf("array: \n"); for(int i = 0; i < MAX_N; i++){ nums[i] = (int)(rand() % (MAX_N * 2) - MAX_N); printf("%d\t", nums[i]); } printf("\n"); printf("The max subsequen sum is %d.\n", maxSubArrayAns(nums)); return 0;}int max3(int a, int b, int c){ if(a > b) return a > c ? a : c; else return b > c ? b : c;}int maxSubArray(int nums[], int left, int right){ int maxLeftSum, maxRightSum; int maxLeftBorderSum, maxRightBorderSum; int leftBorderSum, rightBorderSum; if(left == right) if(nums[left] > 0) return nums[left]; else return 0; int mid = (left + right) / 2, i; maxLeftSum = maxSubArray(nums, left, mid); maxRightSum = maxSubArray(nums, mid + 1, right); maxLeftBorderSum = 0, leftBorderSum = 0; for(i = mid; i >= left; i--){ leftBorderSum += nums[i]; if(leftBorderSum > maxLeftBorderSum) maxLeftBorderSum = leftBorderSum; } maxRightBorderSum = 0, rightBorderSum = 0; for(i = mid + 1; i <= right; i++){ rightBorderSum += nums[i]; if(rightBorderSum > maxRightBorderSum) maxRightBorderSum = rightBorderSum; } return max3(maxLeftSum, maxRightSum, maxLeftBorderSum + maxRightBorderSum);}int maxSubArrayAns(int nums[]){ return maxSubArray(nums, 0, MAX_N - 1);}
使用分治法的话,平均时间复杂度为Θ(n lg n)。实际上解决最大子序列问题还有一种更加快速的方法,这种方法的时间复杂度是Θ(n),是一种线性的算法
int maxSubArrayAns(int nums[]){ int i, thisSum = 0, maxSum = 0; for(i = 0; i < MAX_N - 1; i++){ thisSum += nums[i]; if(thisSum > maxSum) maxSum = thisSum; else if(thisSum < 0) thisSum = 0; } return maxSum;}
1 0
- [算法学习笔记]分治法——最大子序列和问题
- 最大子序列和问题 分治算法
- 算法导论-分治、最大子序列问题
- 算法导论-分治、最大子序列问题
- 算法导论-分治、最大子序列问题
- 最大子序列和分治算法
- 最大子序列和的分治算法
- 分治法求最大子序列和问题
- 分治法求最大子序列和
- 求序列中最大子序列和(分治算法)
- 借助 求 一个序列中最大和子序列 学习 分治算法 code in C#
- 【算法学习】最大子数组问题的分治法求解
- 数据结构与算法分析 学习笔记——最大子序列求和问题
- 【算法】—— 最大子序列和问题
- 算法笔记1-最大子序列和问题的求解
- [数据结构与算法分析]最大子序列和问题 -学习笔记
- 《算法导论》学习笔记——最大子数组(分治策略,动态规划)
- [leetcode]分治法求解最大子序列问题——Java实现
- IP地址的分类——a,b,c 类是如何划分的
- Android自定义View 简单实现多图片选择控件
- FJ的字符串
- handleBars
- Oracle数据库性能调优(上)
- [算法学习笔记]分治法——最大子序列和问题
- CodeForces 349B
- RMQ算法
- 【Android进阶】ListView使用“内存双缓存+硬盘缓存”加载网络图片
- MFC学习笔记——对话框:路径选择对话框(BROWSEINFO)
- Ubuntu快速上手指南(新手教程)
- 基于Linux上的wifi密码爆破
- 装了多个版本的sqlserver,无法共享1433端口,可以自己指定端口
- Java中String与byte[]的转换