转眼就到了期末复习算法的时候了

真的是一点都不慌啊

算法分析与设计这门课,由于是一门选修课,而且我对算法分析没有过多的热爱,所以没有对这门课程进行全方位的深度的学习与复习,但是我相信,将下列算法的全部思想理解清楚后,如果仅仅是为了考试,应该还是不虚的嘿嘿

具体例题思路分析

一、二分搜索(折半查找)

从前有一个故事是这样的,抱着一沓书出图书馆的时候,门响了,在我一本一本的扫描看是那本书没有借的时候,图书馆大妈过来,麻溜的把我的书分成两叠,一堆一堆的扫,然后拿着那本《算法分析与设计》回头看了我一眼,仿佛在说:二分查找都不会?(其实这并不是二分查找嘿嘿)

定义:

优点比较次数少,查找速度快,平均性能好
缺点要求待查表为有序表,且插入删除困难
因此,折半查找方法适用于不经常变动而查找频繁的有序列表。

  1. 假设表中元素是按升序排列,将表中间位置记录的关键字与查找关键字比较,如果两者相等,则查找成功;
  2. 否则利用中间位置记录将表分成前、后两个子表,如果中间位置记录的关键字大于查找关键字,则进一步查找前一子表,否则进一步查找后一子表。
  3. 重复以上过程,直到找到满足条件的记录,使查找成功,或直到子表不存在为止,此时查找不成功。

时间复杂度:

当第一次选取中间位置时,选取的元素等于所要查找的元素则时间复杂度最短,为O(1)
当在最坏情况下,循环被执行O(logn)

算法实现:

在这里推荐一下:二分查找有几种写法?它们的区别是什么?
- 回答作者: 胖胖 https://zhihu.com/question/36132386/answer/155438728

在答主的回答里面提到了许多二分算法存在的坑,这也就是为什么说十个二分九个错的原因了嘿

这里我就直接贴上代码了

/*** Created by Peter Chen on 2017/5/18.* 常规算法*/
function firstOccurrence(arrays,target){var high = arrays.length - 1;var low = 0;while(low <= high){var mid = low + (high - low) / 2;if(arrays[mid] >= target) high = mid - 1;if(arrays[mid] < target) low = mid + 1;}return low;
}
/*** Created by Peter Chen on 2017/5/18.* 递归算法*/
function firstOccurrenceRecur(arrays,target,high,low){if(low > high) return low;var mid = low + (high - low) / 2;if(arrays[mid] >= target)firstOccurrenceRecur(arrays,target,mid - 1,low);else{firstOccurrenceRecur(arrays,target,high,mid + 1);}
}

二、合并排序(归并排序)

定义:

原理:归并排序是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。
优势:使用它对两个己有序的序列归并,将有无比巨大的优势。其时间复杂度无论是在最好情况下还是在最坏情况下均是O(nlogn),且对数据的有序性不敏感。
缺点:需要与待排序序列一样多的辅助空间,所以数据节点数据量大,则不适合使用

时间复杂度:

最坏时间复杂度 :O(nlogn)
最好时间复杂度 :O(nlogn)
空间复杂度 :O(n)
与快速排序类似

算法实现:

原始数组:{3,8,2,4,1,9,6,5}
初始关键字:[3] [8] [2] [4] [1] [9] [6] [5]
一趟归并后:[3 8] [2 4] [1 9] [5 6]
二趟归并后:[2 3 4 8] [1 5 6 9]
三趟归并后:[1 2 3 4 5 6 8 9]

/*** Created by Peter Chen on 2017/5/18.* 自上而下的归并排序*/
function mergeSort(arr) {var len = arr.length;if(len < 2)return arr;var mid = Math.floor(len / 2),left = arr.slice(0,mid),right = arr.slice(mid);return merge(mergeSort(left),mergeSort(right));
}function merge(left,right) {var result = [];while(left.length > 0 && right.length > 0){if(left[0] <= right[0])result.push(left.shift());elseresult.push(right.shift());}while(left.length)result.push(left.shift());while(right.length)result.push(right.shift());return result;
} 

三、快速排序

定义:

原理:快速排序(Quicksort)是对冒泡排序的一种改进。它的基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。

优势:插入排序在对几乎已经排好序的数据操作时,效率高,即可以达到线性排序的效率。
缺点:不稳定,在序列有序或者逆序的情况下最不利于发挥其长处

时间复杂度:

快速排序的最坏运行情况是O(n²)
平均期望时间是O(nlog n)

算法实现:

推荐阅读文章:http://developer.51cto.com/art/201403/430986.htm 文章内容非常浅显易懂!!

/*** Created by Peter Chen on 2017/5/18.*/
function quickSort(arr,left,right) {var len = arr.length,partitionIndex;left = typeof left != 'number' ? 0 : left;right = typeof right != 'number' ? len - 1 : right;if(left < right){partitionIndex = paitition(arr,left,right);quickSort(arr,left,partitionIndex - 1);quickSort(arr,partitionIndex + 1,right);}return arr;
}
function partition(arr,left,right) {//分区操作设定基准值var pivot = left,index = pivot + 1;for(i = index;i <= right;i++){if(arr[i] < arr[pivot]){swap(arr,i,index);index++;}}swap(arr,pivot,index - 1);return index - 1;
}
function swap(arr,i,j) {var temp = arr[i];arr[i] = arr[j];arr[j] = temp;
}

书本算法

template <class Type>void RandomizedQuickSort(Type a[], int p, int r)//给定数组a,数组起始和终止位置p,r
{if (p < r) {int q = RandomizedPartition(a, p, r);//随机选取起始点,此时已排好第一次RandomizedQuickSort(a, p, q - 1);//对前半部分进行递归排序RandomizedQuickSort(a, q + 1, r);//对后半部分进行递归排序}
}
int RandomizedPartition(Type a[], int p, int r) {int i = Random(p, r);Swap(a[i], a[p]);//将选出的元素放置到数组头return Partition(a, p, r);//进行第一次快速排序
}
int Partition(Type a[], int p, int r) {int i = p, i = r + 1;//给哨兵赋初值Type x = a[p];//和x进行大小比较while (true) {while (a[++i] < x && i < r);//从前找到比X大的while (a[--j] > x);//从后找到比X小的if (i >= j) break;//判断两哨兵是否相遇Swap(a[i], a[j]);//两者交换}a[p] = a[j];a[j] = x;//将比较元素放置数组中间return j;//返回第一次快速排序中间位置的元素
}

四、矩阵连乘(动态规划)

定义:


优化思路: A*B*C = (A*B)C = A(B*C)[即寻找最小乘法数]
条件: 具有优化子结构,具有重叠子问题

时间复杂度:

O(p*q*r)=O(n3)
空间复杂性为O(n3)

算法实现:

思路:建立一个矩阵A[i,j]
每一项m[i,j]=计算Ai~jde 最小乘法数
m[1,n]=计算A1~n的最小乘法数
m[i,i]=计算Ai~i的最小乘法数
m[i,j]=m[i,k]+m[k+1,j]+pi-1pkpj

五、最长公共子序列(动态规划)

LCS(Longest Common Subsequence)

定义:

一个数列 ,如果分别是两个或多个已知数列的子序列,且是所有符合此条件序列中最长的,则 称为已知序列的最长公共子序列。

时间复杂度:

(i,j)两层循环,i循环m步,j循环n步 复杂度为O(mn)

算法实现:

六、01背包(动态规划)

定义:

你穿越到了神秘海域中,发现了各种各样的宝藏(W1,W2,W3,W4)价值(P1,P2,P3,P4)。但是此时你哥对你说,你只有一个背包(容量为W),怎么样才能把最大价值的东西带回家咧?并且必须带完整的物品(01)。
优化思路:其实说到底,也就是你看见东西往不往包里放而已。
怎么判断呢?当然是放了的价值和不放的价值那个更大,取那个对吧。
状态转移方程为f[i][v]=max{f[i-1][v](没放),f[i-1][v-c[i]]+w[i](放了)}(这件物品的体积是c[i],价值是w[i])
条件:具有优化子结构,具有重叠子问题

时间复杂度:

O(VN)

算法实现:

function max(a, b) {return (a > b) ? a : b;
}
function dKnapsack(capacity, size, value, n) {//初始化var K = [];for(var i = 0; i <=capacity + 1; i++) {K[i] = [];}//第一层循环商品个数for(var i = 0; i <= n; i++) {//第二层循环背包容量for (var w = 0; w <= capacity; w++) {if(i == 0 || w == 0) {//初始为0k[i][w] = 0;}else if (size[i - 1] <= w) {//若可以放入则选择较大的放入K[i][w] = max(value[i - 1] + K[i - 1][w-size[i - 1]],K[i - 1][w]);}else {//若无法放下,则不放入K[i][w] = K[i - 1][w];}putstr(K[i][w] + " ");}print();}return K[n][capacity];
}
//测试
var value = [4, 5, 10, 11, 13];
var size = [3, 4, 7, 8, 9];
var capacity = 16;
var n = 5;
print(dKnapsack(capacity, size, value, n));

七、哈夫曼编码(贪心算法)

定义: 使用变长码根据字符出现的频率进行编码,可以达到文件压缩的效果

前缀码:任意字符的代码都不是其他字符

特点:具有贪心选择性,最优子结构

时间复杂度:

最小堆实现:初始化优先队列需要O(n),由于最小堆的DeleteMin和Insert运算均需O(logn)时间,n-1次的合并共需要O(nlogn)计算时间,因此,关于n个字符的哈夫曼算法的计算时间为O(nlogn)

算法实现:

template <class Type>
class Huffman {friend BinaryTree<int> HuffmanTree(Type[], int);public :operator Type() const { return weight; }private:BinaryTree<int>tree;Type weight;
};BinaryTree<int>HuffmanTree(Type f[], int n)
{//生成单节点树,并初始化Huffman<Type> *w = new Huffman<Type>[n + 1];BinaryTree <int>z, zero;for (int i = 1; i <= n; i++) {z.MakeTree(i, zero, zero);w[i].weight = f[i];w[i].tree = z;}//建立优先队列MinHeap<Huffman<Type>>Q(1);Q.Initialize(w, n, n);//反复合并最小序频率树Huffman<Type>x, y;for (int i = 1; i < n; i++) {Q.DeleteMin(x);Q.DeleteMin(y);z.MakeTree(0, x.tree, y.tree);x.weight += y.weight; x.tree = z;Q.Insert(x);}Q.DeleteMin(x);Q.Deactivate();delete[]w;return x.tree;
}

八、单源最短路径(Dijkstra算法)

定义:

一个指定点到其余各点的最短路径

时间复杂度:

通过矩阵存储有向图边的数据,则时间复杂度为O(N2)

算法实现:

参见我的另外一篇文章:
http://blog.csdn.net/weixin_31347831/article/details/72520615

九、旅行售货员问题

定义:

时间复杂度:

算法实现:

十、最小生成树

定义: 设G=(V,E)是无向连通带权图,即一个网络。E中每条边(v,w)的权为c[v][w]。如果G的一个子图G·是一棵包含了G的所有顶点的数,则称G·为G的生成树。生成树上各边权的总和称为G的最小生成树。

Prim:按照更新顶点Lowcost排序
Kruskal:按照权递增排序

时间复杂度:

Prim算法的时间复杂度为O(n2)
Kruskal算法的时间复杂度在图的边数为e时,为O(eloge)
当e=欧米伽(n2)时,K算法比P算法差,但当e=o(n2)时,Kruskal算法那比Prim算法好

算法实现:

PRIM算法

template<class Type>
void Prim(int n, Type **c)
{Type lowcost[maxint];int closest[maxint];bool s[maxint];s[1] = true;for (int i = 2; i <= n; i++){lowcost[i] = c[1][i];//表示以i为终点的最小权值closest[i] = 1;//初始化和1相邻s[i] = false;//都没连接}for (int i = 1; i < n; i++) {//重复n-1次,完成算法Type min = inf;int j = 1;for(int k = 2; k <= n;k++)//遍历所有没有连接的点,找出min,并连接if ((lowcost[k] < min) && (!s[k])) { min = lowcost[k]; j = k; }cout << j << '' << closest[j] << endl;s[j] = true;for(int k = 2;k <=n;k++)//根据连接的点进行更新if ((c[j][k] < lowcost[k] && (!s[k])) { lowcost[k] = c[j][k]; closest[k] = j; }}
}

Kruskal

class EdgeNode {friend ostream & operator << (ostream&, EdgeNode<Type>);friend bool Kruskal(int, int, EdgeeNode<Type>*, EdgeNode<Type>*);friend void main(void);
public:operator Type() const { return weight; }
private :Type weight;int u, v;
}bool Kruskal(int n, int e, EdgeNode<Type>E[], EdgeNode<Type> t[])
{MinHeap<EdgeNode<Type>>H(1);H.Initialize(E, e, e);UnionFind U(n);int k = 0;while (e && k < n - 1) {//按权递增,找出连接两个不同分支的T1T2中的顶点时,用边形成连通分支EdgeNode<int > x;H.DeleteMin(x);e--;int a = U.Find(x, u);int b = U.Find(x, v);if (a != b) { t[k++] = x; U.Union(a, b); }}H.Deactivate();return (k == n - 1);
}

一周搞定期末考系列之《算法分析与设计》相关推荐

  1. 【一周搞定计算机网络】计算机网络第5章(运输层)

    [一周搞定计算机网络]文章全系列已经更新完毕,详情请戳: 计算机网络第1章(概述) 计算机网络第2章(物理层) 计算机网络第3章(数据链路层) 计算机网络第4章(网络层) 计算机网络第5章(运输层) ...

  2. 为什么别人一周搞定Linux,而你却做不到

    我给大家精选准备了4段Shell实战脚本 / 基础Linux常用命令: 也许能解决你很多实际工作问题: 如果看到这些你不知道它能用来干嘛,先收藏.先记住吧,以后用的上- 实战命令一: 在实际的工作中, ...

  3. 卜若的代码笔记-一周搞定树莓派-第二十七章:蓝牙模块

    1 这个实验是这样的 板载蓝牙模块,也就是树莓派本身拥有一个蓝牙模块. 然后给你一个外部蓝牙模块HC-05 让你干嘛呢,让你通过外设蓝牙模块发送一条消息给板载蓝牙模块,然后去点亮LED 点亮LED本身 ...

  4. 搞定QQ游戏系列(寻仙,DNF等等)驱动保护TesSafe.sys

    1.用RKU看一下SSDT和SSDTShadow,发现SSDT并没有被HOOK,SSDTShadow HOOK了5个调用: NtUserBuildHwndList NtUserFindWindowEx ...

  5. 过NP 系列之一---搞定QQ游戏系列(寻仙,DNF等等)驱动保护TesSafe.sys

    1.用RKU看一下SSDT和SSDTShadow,发现SSDT并没有被HOOK,SSDTShadow HOOK了5个调用: NtUserBuildHwndList NtUserFindWindowEx ...

  6. 爆火AIGC产品卷翻海外营销:AI一键搞定美工和拍摄,抠图PS设计样样精通,月活迅速破百万...

    允中 发自 凹非寺 量子位 | 公众号 QbitAI 第一批被AI抢饭碗的设计师已经出现了. 随着各个互联网大厂纷纷发布如何将AI工具融入日常工作流中,美工.设计.原画等众多岗位纷纷出现了裁员爆料,毫 ...

  7. 卜若的代码笔记-一周搞定树莓派-第十九章:树莓派使用Git

    1 你果然还是讨厌在树莓派上直接开发QT 毕竟实在是太卡了!!! 你选择在windows上开发,然后再通过某种方式同步到树莓派上面去 于是你盯上了git 你查阅了百度,然后使用命令:git -vers ...

  8. 清华大作业指导:一人单刷雨课堂需要多少工作量?快手工程师详解如何两周搞定...

    点击上方"视学算法",选择加"星标"或"置顶" 重磅干货,第一时间送达 本文转载自:机器之心 昨天,清华自动化大一学生的 C++大作业霸占了 ...

  9. SqlSever2005 一千万条以上记录分页数据库优化经验总结【索引优化 + 代码优化】一周搞定...

    对普通开发人员来说经常能接触到上千万条数据优化的机会也不是很多,这里还是要感谢公司提供了这样的一个环境,而且公司让我来做优化工作.当数据库中的记录不超过10万条时,很难分辨出开发人员的水平有多高,当数 ...

最新文章

  1. 从专利数量看全球最具创新力的50家公司
  2. 除了 k8s,留给 k 和 s 中间的数字不多了!
  3. uboot启动过程中关闭Caches
  4. 解锁一个新技巧,让你舒服到不想起床
  5. python中难的算法_Python算法很难吗?python神书《算法图解》PDF电子版分享给你
  6. 数据挖掘初次接触!学习代码
  7. WEB安全基础-CSRF漏洞
  8. 内网嗅探自我保护用到的批处理
  9. 使用localhost访问远程tensorboard
  10. 蚂蚁警告:“‘includeantruntime‘未设置”
  11. web安全day34:一步一步学习Linux防火墙
  12. Optimus双显卡笔记本上用MediaCoder转换iPhone/iPod 4视频
  13. IIS6配置和PHP5.6环境安装
  14. 数据库推荐,qPCR引物设计与评价
  15. 四级信息安全工程师考试大纲
  16. 关于sip软电话嵌入到网页web端的学习----第一天(1)(高手指点)
  17. 架构师的岗位职责和要求
  18. 关于JavaScript打印去掉页眉页脚
  19. 微信小程序踩坑——项目内文件夹删除不掉
  20. ASA Failover

热门文章

  1. 天玑1200来了,2021年旗舰手机迎体验新趋势
  2. 我的 2020 年总结
  3. 基于matlab的大学生方程式汽车动力性仿真【最高车速、百公里加速时间、75m加速时间、最优传动比】
  4. 提取SaveFileDialog的保存路径
  5. 找电子书不求人,搭建个自己的 zlibrary
  6. springboot 集成dubbo问题
  7. 利用网络爬虫备份某论坛历史数据
  8. 提效利器,定时器软件,小巧、绿色、免费~
  9. 安全大师们的自留地地址
  10. “西湖论剑”四大观察:十年筑梦向未来,数字安全开新局