算法导论学习笔记 一 分治算法
2016-02-17 16:16
274 查看
分治策略是一种常见的算法。在分治策略中,我们递归的求解一个问题,在每层递归中应用如下三个步骤: 1. 分解,将问题分解成规模更小但解决方案相同的子问题 2. 解决,递归的求解子问题,如果子问题足够小则停止递归,直接求解 3. 合并,将子问题的解组合成原问题的解
![](http://i.imgur.com/K4HuEf4.jpg)
![](http://i.imgur.com/nT8zclC.jpg)
最大字数组在左半部分
最大字数组在右半部分
最大字数组起点在左半部分,终点在右半部分
对于前两种情况,我们的求解方式和分解前是相同的,我们需要单独处理第三种情况。
如图:
![](http://i.imgur.com/mAJQJHb.jpg)
那么我们给出解这个问题的思路:
自己尝试用C#实现了下,托管在了github上
最大字数组问题
给你一段股市的波动图,找到在什么时候买入,什么时候卖出能获得最大的收益。![](http://i.imgur.com/K4HuEf4.jpg)
暴力破解法
我们很容易的想到一个包里破解法,就是把所有买入,卖出的组合列举出来进行对比,n天中取任意两天作为买入日和卖出日,共有n*(n-1)/2种解法,因此这种解法的时间复杂度是O(n^2)。问题变换
为了方便我们处理,我们把每个数组的值变为股票的净增量。这个时候,最佳解法就变成了求一个数组的最大字数组:![](http://i.imgur.com/nT8zclC.jpg)
使用分治策略的求解法
我们可以认为,我们要寻找子数组array[start,end]的最大字数组分三种情况:最大字数组在左半部分
最大字数组在右半部分
最大字数组起点在左半部分,终点在右半部分
对于前两种情况,我们的求解方式和分解前是相同的,我们需要单独处理第三种情况。
如图:
![](http://i.imgur.com/mAJQJHb.jpg)
那么我们给出解这个问题的思路:
FindMaxCrossingSubArray(array,start,end) mid=(start+end)/2 从mid开始向左找,找到以mid为终点的最大字数组为array[max-left,min] 从mid开始向右找,找到以mid为起点的最大字数组array[min,max-right] 跨越mid的最大字数组为array[max-left,max-right] max-leftchild =FindMaxCrossingSubArray(array,start,mid) max-rightchild =FindMaxCrossingSubArray(array,min,end) return max-leftchild,max-rightchild,array[max-left,max-right] 3个中的最大字数组
分治算法分析
这种方法我们需要遍历的次数会比n^2少一些,时间复杂度为O(nlgn)代码实现
public int[] FindRecrusive(int[] array, int low, int high) { Console.WriteLine("low {0}, high {1}", low, high); if (low == high) { return new[] { low, high, array[low] }; } int mid = (low + high) / 2; int leftmaxsum = int.MinValue; int currentleftsum = 0; int leftmaxlocation = mid; for (int i = mid; i >= low; i--) { currentleftsum += array[i]; if (currentleftsum > leftmaxsum) { leftmaxsum = currentleftsum; leftmaxlocation = i; } } int rightmaxsum = 0; int currentrightsum = 0; int rightmaxlocation = mid; for (int j = mid + 1; j <= high; j++) { currentrightsum += array[j]; if (currentrightsum > rightmaxsum) { rightmaxsum = currentrightsum; rightmaxlocation = j; } } int[] result = new[] { leftmaxlocation, rightmaxlocation, leftmaxsum + rightmaxsum }; int[] leftresult = FindRecrusive(array, 0, mid); if (leftresult[2] > result[2]) { result = leftresult; } int[] rightresult = FindRecrusive(array, mid + 1, high); if (rightresult[2] > result[2]) { result = rightresult; } return result; }
自己尝试用C#实现了下,托管在了github上
相关文章推荐
- 碰到的C语言的关于循环取数的方法
- Tomcat的生命周期管理
- jenkins git can't work ERROR: Timeout after 10 minutes ERROR: Error fetching remote repo 'origin'
- mac上idea的bug,new project 的时候一定要让idea自己去新建路径!!
- 集训队专题(5.1)1003 maximum shortest distance
- window.open打开的页面向父页面传值
- ie浏览器 spring mvc返回json数据弹出下载页面 解决方案
- 公元2016年2月17日。天朗气清。
- 将TXT文件中的数据整理成sql数据库
- SQL merge into 表合并
- 面试小点。
- 2015-2016-2 《网络攻防实践》教学进程
- DOM编程
- HTTP协议详解
- python auto send email
- iptables踩坑记
- Android绑定方式开始服务&调用服务当中的方法
- 测试基本概念与术语
- 工信部:禁止外资参与网络出版 外国游戏国内要玩完?
- 工信部:禁止外资参与网络出版 外国游戏国内要玩完?