目录
0-1背包问题:给定n种物品和一背包。物体i的重量是wi,其价值为vi,背包的容量为c。如何选择人装入背包的物品,使得装入背包中的物品的总价值最大
背包问题:有n种物品,每种物品只有一个,第i种物品的重量为编辑,价值为编辑,背包的容量为W,物品可以分割。如何放置物品,使得背包的物品价值最大?算法复杂度:O(nlogn)
前言
期末到啦,对自己复习进行一个梳理和总结
主要是基于《计算机算法设计和分析》第5 版的前五章,算法概述、递归与分治策略、动态规划、贪心算法、回溯法。
一、算法概述
算法与程序
- 用计算机求解问题的步骤: 1、问题分析 2、数学模型建立 3、算法设计与选择 4、算法指标 5、算法分析 6、算法实现 7、程序调试 8、结果整理文档编制
- 算法定义: 由若干条指令组成的有穷序列(解决问题的一种方法或一个过程)
- 算法的三要素: 1、操作 2、控制结构 3、数据结构
- 算法具有以下5个属性:
- 有穷性:一个算法必须总是在执行有穷步之后结束,且每一步都在有穷时间内完成。
- 确定性:算法中每一条指令必须有确切的含义。
- 不存在二义性。只有一个入口和一个出口 可行性:一个算法是可行的就是算法描述的操作是可以通过已经实现的基本运算执行有限次来实现的。
- 输入:一个算法有零个或多个输入,这些输入取自于某个特定对象的集合。
- 输出:一个算法有一个或多个输出,这些输出同输入有着某些特定关系的量。
5.算法设计的质量指标:
- 正确性:算法应满足具体问题的需求;
- 可读性:算法应该好读,以有利于读者对程序的理解;
- 健壮性:算法应具有容错处理,当输入为非法数据时,算法应对其作出反应,而不是产生莫名其妙的输出结果。
- 效率与存储量需求:效率指的是算法执行的时间;
- 存储量需求指算法执行过程中所需要的最大存储空间。一般这两者与问题的规模有关。
算法复杂度分析
- 在进行问题的计算复杂性分析之前,首先必须建立求解问题所用的计算模型。
3个基本计算模型是:随机存取机RAM(Random Access Machine);随机存取存储程序机RASP(Random Access Stored Program Machine);图灵机(Turing Machine)
- 衡量算法好坏的标准——时间复杂度高低。
- 可操作性最好且最有实际价值的是最坏情况下的时间复杂性。
主定理(重点)PS:抱上面的博主大大的图,真的讲解的很详细!
- 大Ω符号用来描述增长率的下限,下限的阶越低,结果就越有价值。
NP完全理论
- P(Polynomial问题):也即是多项式复杂程度的问题。
- NP就是Non-deterministic Polynomial的问题,也即是多项式复杂程度的非确定性问题。
- NPC(NP Complete)问题,这种问题只有把解域里面的所有可能都穷举了之后才能得出答案,这样的问题是NP里面最难的问题,这种问题就是NPC问题。
二、递归与分治策略
递归(自顶向下)
分治策略(自顶向下)
- 分治法的基本思想是: 将一个规模为n的问题分解为k个规模较小的子问题,这些子问题互相独立且与原问题相同。递归地解这些子问题,然后将各个子问题的解合并得到原问题的解。
- 分治法所能解决的问题一般具有以下几个特征(重点):
PS:其实就是基本思想而已
(1)该问题的规模缩小到一定的程度就可以容易地解决;
(2)该问题可以分解为若干个规模较小的相同问题,即该问题具有最优子结构性质;
(3)利用该问题分解出的子问题的解可以合并为该问题的解;
(4)该问题所分解出的各个子问题是相互独立的,即子问题之间不包含公共的子问题。
3.分治法的基本步骤: 分治法在每一层递归上都有三个步骤:
(1)分解:将原问题分解为若干个规模较小,相互独立,与原问题形式相同的子问题;
(2)解决:若子问题规模较小而容易被解决则直接解,否则递归地解各个子问题;
(3)合并:将各个子问题的解合并为原问题的解。
二分搜索:二分搜索是一种在有序数组中查找特定元素的搜索算法,它使用二分法来查找特定的目标值,在每一步中将搜索空间减少一半,从而使搜索更有效率。
时间复杂度:log(n)
例题:给定已按升序排好序的n个元素a[0:n-1],现要在这n个元素中找出一特定元素x。 据此容易设计出二分搜索算法:
//二分搜索算法 tempalte<class Type> int BinarySearch(Type a[],const Type& x,int l,int r) { while(l<=r){ int m=((l+r)/2): if(x==a[m]) return m; if(x<a[m]) r=m-1; else l=m+1; } return -1; }
快速排序:性能取决于划分的对称性
template <class Type> void QuickSort(Type a[], int p, int r) { if (p < r) { int q = Partition(a, p, r) ; QuickSort(a, p, q - 1); // 对左半端排序 QuickSort(a, q + 1, r); // 对右半段排序 } } int Partition(Type a[], int p, int r) { int i = p, j = r + 1; Type x = a[p]; // 将小于x的元素交换到左边区域,将大于x的元素交换到右边区域 while (true) { while (a[++i] < x && i < r) ; while (a[--j] > x) ; if (i >= j) break; Swap(a[i], a[j]); } a[p] = a[j]; a[j] = x; return j; }
合并排序:(基本思想)将待排序元素分成大小大致相同的两个子集合,分别对两个子集合进行排序,最终将排好序的子集合合并成要求的排好序的集合。时间复杂度:O(nlogn)
template <class Type> void MergeSort(Type a[], int left, int