三、算法设计与分析
一、分治法
1.1 分而治之
对于一个规模为n的问题,若该问题可以容易的解决(比如说规模较小,则直接解决,否则将其分解为k个规模较小的问题,这些子问题相互独立且与原问题形式相同,递归地解决这些子问题,然后将各子问题的解合并得到原问题的解。
要求:
- 该问题的规模缩小到一定程度就可以容易地解决。
- 该问题可以分解为若干规模较小的相同问题。
- 利用该问题分解出的子问题的解可以合并为该问题的解。
- 该问题所分解出的各个子问题是相互独立的。
一般来说,分治算法在每一层递归上都有3个步骤。
- 分解。将原问题分解成一系列子问题。
- 求解。递归地求解各子问题。若子问题足够小,则直接求解。
- 合并,将子问题的解合并成原问题的解。
1.2 递归
递归:就是在运行过程中调用自己。
#include<stdio.h>
int muliplyNumbers(int n) ;
int main(){
int n;
printf("输入一个整数:");
scanf("%d",&n);
printf("%d != %ld",n,multiplyNumbers());
return 0;
}
int muliplyNumbers(int n)
{
if(n>1){
return n* muliplyNumbers(n-1);
}
else return 1;
}
函数递归调用带来的内存开销:
S(n)=O(n)
空间复杂度=递归调用的深度
例题
快速排序算法在排序过程中,在待排序数组中确定一个元素为基准元素,根据基准元素把待排序数组划分成两个部分,前面一部分元素值小于基准元素,而后面一部分元素值大于基准元素。然后再分别对前后两个部分进步进行划分根据上述描述,快速排序算法采用了( )算法设计策略。已知确定着基准元素操作的时间复杂度为( )
A.分治 B.动态规划 C.贪心 D.回溯
A . O ( n ) 和 O ( n l g n ) B . O ( n ) 和 O ( n 2 ) C . O ( n l g n ) 和 O ( n l g n ) D . O ( n l g n ) 和 O ( n 2 ) A.O(n)和O(nlgn) \quad \quad\quad B.O(n)和O(n^2) \\ C.O(nlgn)和O(nlgn) \quad \quad\quad D.O(nlgn)和O(n^2) A.O(n)和O(nlgn)B.O(n)和O(n2)C.O(nlgn)和O(nlgn)D.O(nlgn)和O(n2)
AD
二、回溯法
2.1 深度优先搜索法
回溯法是种选优搜索法,按选优条件向前搜索,以达到目标。但当搜索到某一步时,发现原先选择并不优或达不到目标,就退回一步重新选择。这种走不通就退回再走的技术就是回溯法。
三、贪心法
3.1 局部最优
总是做出在当前来说是最好的选择,而并不是从整体上加以考虑,它所做出的每步选择只是当前步骤的局部最优选择,但从整体来说不一定是最优的选择。由于它不必为了寻找最优解而穷尽所有的可能解,因此其耗费时间少,一般可以快速得到满意的解,但得不到最优解。也常用于解决最优化问题。
用贪心法求解的问题一般具有两个重要的性质。
- 最优子结构。当一个问题的最优解包含其子问题的最优解时,称此问题具有最优子结构。问题的最优子机构是该问题可以采用动态规划法或者贪心法求解的关键性质。
- 贪心选择性质。指问题的整体最优解可以通过一系列局部最优的选择,即贪心选择得到。这是贪心法和动态规划的主要区别。
四、动态规划法
4.1 子问题独立(区别分治法)
基本思想是将求解问题分解成若干子问题,先求解子问题,燃弧从这些子问题的解得到原问题的解。
与分治法不同的是,适合于用动态规划法求解的问题,经分解得到的子问题往往不是独立的。
动态规划算法通常用于求解具有某种最优性质的问题。在这类问题中,可能会有许多可行解,每个解都对应一个值,我们希望找到具有最优值的那个解。当然,最优解可能会有多个,动态规划算法能找出其中的一个最优解。
4.2 整体最优(区别贪心法)
对一个给定的问题,若其具有以下两个性质,则可以考虑用动态规划法来求解。
- 最优子结构。如果一个问题的最优解中包含了其子问题的最优解,就说该问题具有最优子结构。当一个问题具有最优子结构时,提示我们动态规划法可能适用,但是此时贪心策略可能也是适用的。
- 重叠子问题。指用来求解原问题的递归算法可反复地解同样的子问题,而不是总在产生新的子问题。即当一个递归算法不断地调用同一个问题时,就说该问题包含重叠子问题。此时若用分治法递归求解,则每次遇到子问题都活视为新问题,会极大地降低算法效率,而动态规划法总是充分利用重叠子问题,对每个子问题仅计算一次,把解保存在一个需要时就可以查看的表中,而每次查表的时间为常数。
考虑一个背包问题,共有5个物品,背包容量为W=10,物品重量和价值分别w={2,2,6,5,4},v={6,3,5,4,6},求解背包问题的最大装包价值。若此为0-1背包问题,分析该问题具有最优子结构,定义递归式为
c(i,j)=\left{
\begin{aligned}
0 \quad \quad\quad \quad\quad \quad\quad \quad 若i=0或j=0\
c(i-1) \quad \quad\quad \quad\quad \quad \quad \quad 若w[i]>j \
max{c(i-1),c(i-1,j-w(i))}\quad\quad 其他
\end{aligned}
\right.
$$
$$A . 11 B . 14 C . 15 D . 16.67 A . O ( n W ) B . O ( n l g n ) C . O ( n 2 ) D . O ( n l g n W ) A.11\quad \quad B.14 \quad \quad C.15 \quad \quad D.16.67 \\ A.O(nW)\quad \quad B.O(nlgn)\quad \quad C.O(n^2) \quad \quad D.O(nlgnW) A.11B.14C.15D.16.67A.O(nW)B.O(nlgn)C.O(n2)D.O(nlgnW)
CA
考虑一个背包问题,共有5个物品,背包容量为W=10,物品重量和价值分别w={2,2,6,5,4},v={6,3,5,4,6},求解背包问题的最大装包价值。若此为部分背包问题,首先采用归并排序算法,根据物品的单位重量价值从大到小排序,然后依次将物品放入背包直至所有物品放入背包中或者背包再无容量,则得到的最大装包价值为 ( ),算法的时间复杂度为( )。 分析该问题具有最优子结构,定义递归式为
c(i,j)=\left{
\begin{aligned}
0 \quad \quad\quad \quad\quad \quad\quad \quad 若i=0或j=0\
c(i-1) \quad \quad\quad \quad\quad \quad \quad \quad 若w[i]>j \
max{c(i-1),c(i-1,j-w(i))}\quad\quad 其他
\end{aligned}
\right.
$
$$A . 11 B . 14 C . 15 D . 16.67 A . O ( n W ) B . O ( n l g n ) C . O ( n 2 ) D . O ( n l g n W ) A.11\quad \quad B.14 \quad \quad C.15 \quad \quad D.16.67 \\ A.O(nW)\quad \quad B.O(nlgn)\quad \quad C.O(n^2) \quad \quad D.O(nlgnW) A.11B.14C.15D.16.67A.O(nW)B.O(nlgn)C.O(n2)D.O(nlgnW)
DB
O ( 1 ) < O ( l o g 2 n ) < O ( n ) < O ( n l o g 2 n ) < O ( n 2 ) < O ( n 3 ) < O ( 2 n ) < O ( n ! ) < O ( n n ) O(1)<O(log_2n)<O(n)<O(nlog_2n)<O(n^2)<O(n^3)<O(2^n)<O(n!)<O(n^n) O(1)<O(log2n)<O(n)<O(nlog2n)<O(n2)<O(n3)<O(2n)<O(n!)<O(nn)