一 算法
定义:有限步骤内求解某一问题所使用的一组定义明确的规则。 [针对问题的解决方案][ 为解决问题,而采取的方法与步骤] |
内容:设计算法、表示算法、确认算法、分析算法、验证算法 |
特性:有穷性[有限时间执行完毕]、确定性[执行唯一]、可行性、输入、输出 |
表示方法:自然语言、程序流程图、程序【顺序、选择、循环】 |
分类: 同一问题——有多种解决问题的算法 特定问题、特定约束条件——合适的算法 |
二算法分析
算法复杂度
算法复杂度:算法运行所需的资源。 |
1时间复杂度 程序执行次序(频度):f(n)的数量级 公式:T(n) = 0(f(n)) 其中T(n) 就是算法的时间复杂度,n表示是输入到算法的数据模块 常见:0(1)常量级 0(n)线性级 0(n^2)平方级 |
2空间复杂度 |
重点:不超过内存,空间换时间 |
基础算法
递归 |
定义:一个过程[函数],直接\间接调用自己本身的过程[函数] 设计:1确定递归公式 2确定边界条件\终止条件 问题:求数组中最大的数、1+2+。。。+n、求n个整数的平均值、求n个自然数的最大公约数和最小公倍数、生兔子问题、斐波那契数列、汉诺塔同类问题 |
回溯 |
定义: 设计:1用栈保存前进状态 2制定约束条件 问题:全排列、n个皇后 |
排序 |
|
三 算法设计
1原则
原则:正确性、可读性、健壮性、高效率与低存储量 |
1正确性 <1没有语法错误 <2 根据正确的输入的值得到满足要求的输出结果 <3 根据错误的输出的值满足规格说明的输出结果 [正确的标准——] <4 对于精心设计、极其刁难的测试数据满足要求的输出结果 <5 |
2可读性:设计算法的目的是计算机执行\便于阅读——[评判算法] |
3健壮性:输入数据非法时,算法应恰当地做出反应\处理,不中断程序的情况下,返回一个表示错误或者错误性质的值,以便于在更高抽象层次上进行处理 |
4高效率: 算法的效率-算法的执行时间—【时间复杂度】 低存储量:算法的存储量-算法执行过程中所需的最大存储空间—【空间复杂度】 |
2设计步骤
1建立数学模型 分析问题—抽象出数学模型 |
2确定数据结构与算法 确定数据结构—设计对数据结构实施操作的算法 |
3选用语言 算法—转化—程序 |
4调试并运行 |
3设计思想
穷举、递推、递归、分治、概率 |
1穷举算法思想 定义:从所有可能结果 步骤:[计算每种可能的结果]——[判断结果是否符合要求]——[符合,输出][不符合,返回第一步] 问题:鸡兔同笼 |
2递推算法思想 定义:根据已知条件,利用特性关系推导中间推论,直到得到结果 问题:斐波那契数列 等 |
3递归算法思想 定义:大问题转换成同类问题的子问题,然后递归调用函数表示问题的解[终止条件] 问题:求阶乘、 |
4分治算法思想 定义:大问题分解成相互独立的子问题[与原问题性质相同],然后逐步求出子问题的解 问题:查找假币 |
5概率算法思想 数值概率算法、蒙特卡罗算法、拉斯维加斯算法、舍伍德算法 |
设计思路
分治法、动态规划、贪心算法、 |
1分治法 |
一思想 <1定义:将1个规模为n的问题分解为k个规模较小的子问题。[子问题相互独立、且与原问题相同],递归解决子问题,然后将子问题的解合并得到原问题的解。 <2规划子问题: -集合论:原集合问题的划分,子问题不相交且规模类型相同 -最优子结构:子问题类型相同 -子规模相近 <3方法 divide—and—conquer(P) {if(|P|<=n0) adhoc(P); divide P into samller subinstances P1,P2,…Pk; for(int i=1;i<k;i++){yi=divide—and—conquer(Pi);} return merge(y1,y2,…,yn)} 二问题 Fibonacci数列、排列问题、整数规划问题、Hanoi塔问题、二分搜索、合并排序、快速排序、大整数乘法、Strassen矩阵乘法(n行m列选最大的和)、 三复杂度 主定理:T(n)=aT(n/b)+f(n),a>=1,b>1【f(n):给定的多项式函数,刻画分值算法,生成a个子问题,每个问题的规模是原来的1/b,分解合并步骤共消耗f(n)】 T(n)的复杂度: 1若f(n)<n^(log(a/b)),则T(n)=n^(log(a/b)) 2若f(n)=n^(log(a/b)),则T(n)=n^(log(a/b))logn 3若f(n)>n^(log(a/b)),则T(n)=f(n) |
2动态规划 |
一思想 <1定义:用一个表记录所有可以解决问题子问题的答案,不管以后是否会用到,只要计算,就将结果存入表中。 基本要素: 1最优子结构:问题的最优解包含了子问题的最优解 2重叠子问题:递归算法有很多子问题重叠,则用一个表将已经求解过的子问题结果保存。 二基本步骤 【1找出最优解性质,刻画结构特征】—【2递归定义最优值】—【3自底向上计算最优值】— 【4根据计算最优值得到的信息,构造最优解】 三问题 矩阵连乘、最长公共子序列、0-1背包问题 四 应用—备忘录方法 动态规划 备忘录方法 <1相同 用一张表保存子问题的答案,下次求解时查看表的答案,不用重新计算。 <2不同递归方式:自底向上 | 自顶向下 <3使用条件:所有子问题都至少解一次| 部分子问题不必求解 |
3贪心算法 |
一思想 <1定义:不从整体最优考虑,做出的选择只是某种意义上的局部最优选择 <2要素: -贪心选择性质:所求问题的整体最优解可以通过一系列局部最优的选择[贪心选择],来达到 -最优子结构;问题的最优解包含其子问题的最优解 二问题 活动安排问题(最早截止时间优先)、背包问题(权重空间比值最大者优先)、哈夫曼编码(频率大者优先)、单源最短路径(局部最短路径优先)、最小生成树(prim[与源集合相连权值最小边优先]\ kruskal[集合中边权值最小优先])、多级调度问题(长作业优先) 三区别 贪心算法| 动态规划 条件 方法: |
总结:分治divide—and—conquer[Divid—conquer—Combine] |
五 功能问题
图形 |
规律 |
功能 统计: 分页:分页:(y+x-1)/x 逆向运算[结果—推导—>方式] p=(y+x-1)/x |
问题
最佳浏览路线问题 |
删数问题 |
算法分析与设计
P问题、非P问题、NP问题、NPC问题 P问题 非P问题 NP问题 NPC问题 |
|
数字在排序数组中出现次数。
题目:统计一个数字在排序数组中出现的次数。 |
思路:
|
class Solution{ public: int getNumberOfK(vector<int> &data, int begin, int end, int k) { int i = begin,j = end,mid = (i + j)>>1; if(i>j)return 0; if(i==j) return data[mid]==k; if(data[mid]==k) return 1 + getNumberOfK(data,begin,mid-1,k) +getNumberOfK(data,mid+1,end,k); if(data[mid] < k) return getNumberOfK(data,mid + 1,end,k); return getNumberOfK(data ,begin, mid - 1,k); } }; |
http://www.docin.com/p-1945081530.html
递归 |
递推 |
回溯:前进状态、约束条件 |
排序: 选择排序: 插入排序 冒泡排序: 快速排序: 希尔排序 堆排序 二叉树排序 归并排序 线形排序: <1计数排序 <2桶排序 <3基数排序 |
查找 顺序查找 二分查找 二叉树排序查找 哈希表查找:哈希表 |
穷举策略 从可能解的集合中枚举全部元素,条件校验?解:误解 |
贪心策略 从问题的初始状态出发、通过若干次贪心选择,得出最优解 特点:贪心选择性质、局部最优解 |
分治策略(Divide and conquer) 规模为n的问题,分为k规模较小的子问题。递归解决子问题,合并解 [应用:快速排序] |
搜索: 深度优化搜索 过度优化搜索 戴克斯特拉算法 动态规划 朴素贝叶斯分类 |
|
选择排序: 思路: 步骤:排序的序列处理n-1遍。 第一遍:L[1…n]最小者,与L[1]交换位置 第二遍:L[2…n]最小者,与L[2]交换位置 第i遍:L[i…n]最小者,与L[i]交换位置 |
插入排序 思路 步骤:经过i-1遍处理后,L[1,…,i-1]已经排好序. 第i遍处理:将L[i]插入L[1,…,i-1]的适当位置p,原来p后的元素右移 问题: |
冒泡排序=交换排序 思路:对排序的记录的关键字进行两两比较,如果反序,则交换,直到无反序记录。 步骤: |
快速排序 思路:依据分治法策略,一个串行(list)分成一个子串行(sub-list) 步骤 1基准(pivot) :数列中挑出一个元素 2分区(partition): 重新排序,所有元素比基准值小的摆放在基准前面,大的在后面。分区退出后,该基准处于数列的中间位置。 3递归(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序。 |
希尔排序 思路:将整个无序序列分割成若干小的子序列分别进行插入排序、冒泡排序 序列分割: |
堆排序与二叉树排序 堆排序 二叉树排序 |
归并排序Merge sort 思路:依据分治法策略 步骤: 归并:多个有序数列合成一个有序数列 二路归并:两个有序数列合成一个有序数列 归并排序:n长度为1的子序列,两两排序最后变为有序序列。 |
线形排序 计数排序 桶排序 基数排序 |
排序比较: 稳定性:插入\冒泡\二叉树\二路并归\线形-稳定,选择\希尔\快速\堆-不稳定 |
顺序查找:顺序逐个比较, 查找值==结点值?成功:失败 |
二分法查找 思路:从数组中间元素查找,如果查找元素是中间元素, 搜索过程结束\如果查找元素大于\小于中间元素,则在数组大于\小于中间元素那一侧查找—跟开始一样从中间元素开始比较\如果某一步骤数组为空,代表找不到 |
二叉树排序查找 |
哈希表 哈希表\散列表 哈希函数:H(k)=k\H(k)=a*k+b(线性函数) 存储位置K、关键字k 查找:递归方式 |
|
线性查找算法BFPRT 思路:从n个元素的序列中选出第k大\小的元素 步骤:五位算法 1将n个元素每5个一组,分成n/5组(上界) 2取出每组的中位数,任意排序。[插入排序] 3递归调用selection算法查找上一步所有的中位数,设为x,偶数个中位数时,设定为中间小的 4用x分割数组,设小于等于x的个数为k,大于x的个数为n-k 5若i==k,返回x;\若i<k,在小于x的元素递归查找第i小的元素\若i>k,在大于x的元素队规查找第i-k小的元素 |
深度优化算法DFS(Depth-First-Search)【盲目搜索】 思路: 步骤: |
过度优化搜索BFS(Breadth-First-Search) 【图形搜索】 思路: 步骤: |
戴克斯特拉Dijkstra 思路: 步骤: |
动态规划Dynamic programming[数学、计算机、经济学] 定义:复杂问题分解为简单子问题,分别求解,合并解。(耗时少于朴素算法) 适用:有重叠子问题、最优子结构性质问题 步骤:1解决每个子问题一次,从而减少计算量;2一旦某个给定子问题解得出,则记忆化存储;3下次同一个子问题求解时,直接查表 背包问题 |
朴素贝叶斯分类算法 贝叶斯分类:概率推论[各种条件存在不确定,仅知概率,完成推理和决策] 贝叶斯分类器:自然概率模型,独立假设[样本与其他特征不相关] 参数估计:最大似然估计法 思路:基于贝叶斯定理的简单概率分类算法。 步骤: |