数据结构之第一章 引论 及 课后题答案
本章主要是学会对程序时间复杂度的计算分析方法,基于这个目的,需要掌握数学基础、模型等知识点,所以本章的课程结构如下:
- T(N) = O(f(N)) 意思是,T(N)函数的增长率小于等于f(N).如 N=O(N^2)
- T(N) = Ω(f(N)) 意思是,T(N)函数的增长率大于等于f(N).如 N^2=Ω(f(N))
- T(N) = Θ(f(N)) 意思是,T(N)函数的增长率等于f(N)的增长率,如 N = Θ(2N)
- T(N) = o(f(N)) 意思是,T(N)函数的增长率小于f(N),不包括等于.
上面公式定义中,常用的是第一个。此外,还需要记住几个法则:
- T1(N)=O(f(N)) 且 T2(N)=O(g(N)),那么:
T1(N)+T2(N) = max(O(f(N)), O(g(N)))
T1(N)*T2(N) = O(f(N)*g(N))
exp:
N=O(N^2) N^3=O(N^4) ==> N+N^3=max(O(N^2), O(N^4))=O(N^4).
N=O(N^2) N^3=O(N^4) ==> N*N^3=O(N^2*N^4)=O(N^6)
- T(N)是一个k次多项式,则T(N)=Θ(N^k).
exp:
1+N^2+N^3 = Θ(N^3).即左侧的函数增长率与N^3函数的增长率相同。
- 对数函数的增长率缓慢,其次是线性。
模型
略
要分析的问题
1. 最大子序列和
给定A1,A2,A3,….An,求其连续子序列的最大和。所谓子序列,是指在这N个数中的连续的子项组成的集合。比如(A1,A2),(A2,A3,A4),(A1,A2,A3)等,但是(A1,A3)则不属于本文中的子序列概念,因为其下标是不连续的。书中给出了四种解决方案,下面逐一分析。
- 求出所有连续的子序列,逐一求解每个序列的和,然后再取最大的。
#include <iostream>
#include <vector>
using namespace std;
int maxSubSum1( const vector<int> &a )
{
int maxSum = 0;
for(int i=0; i<a.size(); i++ ) //i代表了序列的起始元素下标
{
for(int j=i; j<a.size(); j++ ) //j代表了序列的结束元素下标
{
int thisSum =0;
for( int k=i; k<=j; k++ ) //代表了序列中间的元素下标,逐一遍历即取到子序列的所有元素
{
thisSum += a[k];
cout<<a[k]<<" "<<flush;
}
cout<<endl;
if(thisSum>maxSum)
{
maxSum = thisSum;
}
}
}
return maxSum;
}
该方法比较直观,看代码中的注释,明白计数器的含义,就很简单了。但是该方法循环三次,复杂度是O(N^3)。一般的复杂度法则如下:
一次for循环的复杂度为O(N)
嵌套for循环则为O(N^k)
顺序执行的运行时间即逐句求和即可。复杂度应该如何表示呢?
- 降低复杂度O(N^2)的实现
int maxSubSum2(const vector<int> &a)
{
int maxSum = 0;
for (int i=0;i<a.size();i++)
{
int thisSum=0;
for (int j=i; j<a.size();j++)
{
thisSum += a[j];
if (thisSum>maxSum)
{
maxSum = thisSum;
}
}
}
}
其实没看懂为什么会这样
- 线性复杂度
int maxSubSum3(const vector<int> &a, int left, int right)
{
int maxSum = 0;int thisSum=0;
for (int i=left;i<right;i++)
{
thisSum+=a[i];
if (thisSum>maxSum)
{
maxSum = thisSum;
}else if(thisSum<0)
{
thisSum = 0;
}
}
return maxSum;
}
也是看不懂,就记住吧。
本文主要介绍了数据结构中关于程序时间复杂度的计算分析方法,包括数学基础、模型等内容,并详细解析了最大子序列和问题的不同算法实现及其复杂度。
1471

被折叠的 条评论
为什么被折叠?



