算法导论学习之分治法
来源:互联网 发布:试卷出题软件 编辑:程序博客网 时间:2024/06/05 18:39
分治法的主要思想为将一个大问题转换成一个小问题,再解决每个小问题。主要分为三个步骤:
1、Devide——大问题分解成小的问题
2、Conquer——(递归地)解决小问题
3、Combine——将解合并
下面介绍一些比较常见的运用分治思想的算法。
一、归并排序
归并排序是性能比较好的一种排序方法,它的时间复杂度是O(nlgn),是典型的运用了分治思想的算法。归并排序的步骤如下:
1、分解。将待排序的n个元素分解成n/2的子序列。
2、解决。使用归并排序递归的排列两个子序列。
3、合并。将两个已排序的子序列合并得出结果。
代码如下:
//将有二个有序数列a[first...mid]和a[mid...last]合并。 void mergearray(int a[], int first, int mid, int last, int temp[]) { int i = first, j = mid + 1; int m = mid, n = last; int k = 0; while (i <= m && j <= n) { if (a[i] <= a[j]) temp[k++] = a[i++]; else temp[k++] = a[j++]; } while (i <= m) temp[k++] = a[i++]; while (j <= n) temp[k++] = a[j++]; for (i = 0; i < k; i++) a[first + i] = temp[i]; } void mergesort(int a[], int first, int last, int temp[]) { if (first < last) { int mid = (first + last) / 2; mergesort(a, first, mid, temp); //左边有序 mergesort(a, mid + 1, last, temp); //右边有序 mergearray(a, first, mid, last, temp); //再将二个有序数列合并 } }
下面分析一下归并排序的时间复杂度。归并排序最坏情况运行时间T(n)的递归式如下:
常量c代表求解规模为1的问题所需的时间以及在分解与合并步骤处理每个元素所需的时间。对T(n)进行分解可得如下的树:
由d图可知,这棵树的高度为lg n,每层耗费cn,所以总代价为cn lg n+cn。忽略掉系数和低阶项后可知其时间复杂度为O(n lgn)。
二、幂次方问题
给定一个数x(int/float),和一个正整数n,求x^n。这道题直接用循环做,很简单,但时间复杂度是O(n)。能否改进一下算法,减小时间复杂度呢,这里就要用到分治的思想了。
1、分解。x^n可以分解为x^n/2*x^n/2。
2、解决。(递归)求解每个子问题。
3、合并。将子问题合并。
代码如下:
int flag=0; public double myPow(double x, int n) { if(n == 0) return 1; if(n<0&&flag==0){//处理n为负数时的情况 x = 1/x; flag++;//保证这个if语句只执行一次。因为x=1/x只需要设置一次 } return (n%2 == 0) ? myPow(x*x, n/2) : x*myPow(x*x, n/2); }
这个算法的时间复杂度是O(lg n),比直接使用循环求解性能要好一些。
三、二分查找
在一个有序序列A中查找元素x。这也是一个比较简单的算法,用分治法的步骤如下:
1、分解——将x与序列的中间元素比较
2、解决——(递归地)在子有序数列中查找x
3、合并——什么也不做
代码如下:
代码如下:
int BinarySearchRecursive(int *Array,int x,int Low,int High) //L is the length of the sorted array { int mid; mid = (Low + High + 1)/2 ; if (Low < High) { if (Array[mid] < x) { Low = mid + 1 ; return BinarySearchRecursive(Array,x,Low,High) ; } else if (Array[mid] > x) { High = mid - 1; return BinarySearchRecursive(Array,x,Low,High) ; } else return mid ; } else return -1 ; }总结:分治法最重要的是将一个大问题化为一个小问题,然后各个击破的思想。它虽然是比较简单的一种算法,但如果能够真正掌握其思想并做到融会贯通,也会展现出其强悍的一面。
0 0
- 算法导论学习之分治法
- 算法导论之分治法
- 算法导论之分治法
- 算法导论之分治法
- 【算法导论】分治法
- 算法导论--分治法
- 算法导论学习:分治策略之最大子数组问题
- 分治之最大子数组-《算法导论》学习笔记四
- 算法导论笔记一:算法设计之分治法
- 算法导论:分治法(2)
- 算法导论--分治法--P17
- 算法导论学习1--分治法计算逆序数
- MIT算法导论学习笔记-Lecture3:分治法
- MIT算法导论学习笔记-Lecture4 分治法(续)
- 算法导论第二版笔记之分治法
- 算法导论学习笔记--1--分治排序
- 算法导论学习笔记(一)排序算法之分治排序
- 《算法导论》 2.3.1分治法
- sg函数模板(打表)
- 在一行字符串里查找一个单词
- (转)对冲基金之王科恩,天才还是魔鬼?——读《黑色优势》有感
- mybatis SQL性能调优
- 前端Sass回顾以及Compass入门小记
- 算法导论学习之分治法
- HDU
- 数据结构与算法入门
- C++学习笔记之——友元
- 打造网络营销利器-第3篇--站内链接-网站优化进阶
- 用C++实现的完全二叉树,实现前序遍历,中序遍历,后序遍历。
- Java程序规范
- 每天一个Linux命令(1):ls命令
- 在mybatis执行SQL语句之前进行拦击处理