数据结构与算法读书笔记 - 010 - 时间复杂度02

主要有关大O记法

————————————————————

用表格法以及大O记法来计算时间复杂度

————————————————————

阶乘

lines/efrequencystep sum
long long fractorial(int n)000
{000
if(n < 1) return 1;11Θ(1)
else return n * fractorial(n-1);1n-1Θ(n)
}000
totalΘ(n)

————————————————————

比较不划算的最大最小值index

lines/efrequencystep sum
template < class T >000
bool minMax_1(T a[], int n, int &indexOfMin, int &indexOfMax)000
{000
if(n < 1) return false;11Θ(1)
indexOfMin = indexOfMax = 0;11Θ(1)
for(int i = 0; i < n; ++i)1n+1Θ(n)
{000
if(a[indexOfMin] > a[i]) indexOfMin = i;1nΘ(n)
if(a[indexOfMax] < a[i]) indexOfMax = i;1nΘ(n)
}000
return true;11Θ(1)
}000
totalΘ(n)

————————————————————

稍微划算一点的最大最小值index

lines/efrequencystep sum
template < class T >000
bool minMax_2(T a[], int n, int &indexOfMin, int &indexOfMax)000
{000
if(n < 1) return false;11Θ(1)
indexOfMin = indexOfMin = 0;11Θ(1)
for(int i = 0; i < n; ++i)1n+1Θ(n)
{000
if(a[indexOfMin] > a[i]) indexOfMin = i;1Θ(n)Θ(n)
else if(a[indexOfMax] < a[i]) indexOfMax = i;1Ω(0), O(n)Ω(0), O(n)
}000
return true;11Θ(1)
}000
totalΘ(n)

————————————————————

lines/efrequencystep sum
template < class T >000
void MatrixAdd(T **r, T **a, T **b, int numRow, int numCol)000
{000
for(int i = 0; i < numRow; ++i)1row+1Θ(row)
{000
for(int j = 0; j < numCol; ++j)1(col+1)*rowΘ(row*col)
r[i][j] = a[i][j] + b[i][j];1col*rowΘ(row*col)
}000
}000
totalΘ(row*col)

————————————————————

方阵乘法
啊啊每次写方阵乘法都要从矩阵的几何意义想一遍。记不住定则应该是我数学物理成绩不好的主要原因之一。。。

lines/efrequencystep sum
template < class T >000
void squareMatrixMultiply(T **r, T **left, T **right, int n)000
{000
for(int i = 0; i < n; ++i)1Θ(n)Θ(n)
{000
for(int j = 0; j < n; ++j)1Θ(n2)Θ(n2)
{000
T sum = 0;1Θ(n2)Θ(n2)
for(int k = 0; k < n; ++k)1Θ(n3)Θ(n3)
{000
sum += left[i][k] * right[k][j];1Θ(n3)Θ(n3)
}000
r[i][j] = sum;1Θ(n2)Θ(n2)
}000
}000
}000
totalΘ(n3)

————————————————————

非方阵的矩阵乘法

lines/efrequencystep sum
template < class T >000
//left m * n000
//right n * p000
//r m * p000
void matrixMultiply(T **r, T **left, T **right, int m, int n, int p)000
{000
for(int i = 0; i < m; ++i)1Θ(m)Θ(m)
{000
for(int j = 0; j < p; ++j)1Θ(mp)Θ(mp)
{000
T sum = 0;1Θ(mp)Θ(mp)
for(int k = 0; k < n; ++k)1Θ(mpn)Θ(mpn)
{000
sum += left[i][k] * right[k][j];1Θ(mpn)Θ(mpn)
}000
r[i][j] = sum;1Θ(mp)Θ(mp)
}000
}000
}000
totalΘ(mpn)

————————————————————

最大元素index

lines/efrequencystep sum
template < class T >000
int indexOfMax(T a[], int n)000
{000
if(n < 1) return -1;11Θ(1)
int index = 0;11Θ(1)
for(int i = 1; i < n; ++i)1nΘ(n)
{000
if(a[index] < a[i])1nΘ(n)
index = i;1Ω(0), O(n-1)Ω(0), O(n)
}000
return index;111
}000
totalΘ(n)

————————————————————

多项式乘法

lines/efrequencystep sum
template < class T >000
T polyEval(T coeff[], int n, const T &x)000
{000
T xIndex = 1, value = coeff[0];11Θ(1)
for(int i = 1; i < n; ++i)1nΘ(n)
{000
xIndex *= x;1n-1Θ(n)
value += coeff[i] * xIndex;11Θ(n)
}000
return value;11Θ(1)
}000
totalΘ(n)

————————————————————

lines/efrequencystep sum
template < class T >000
T horner(T coeff[], int n, const T &x)000
{000
T value = coeff[n-1];111
for(int i = n-2; i >= 0; --i)1nΘ(n)
{000
value = value * x + coeff[i];1n-1Θ(n)
}000
return value;111
}000
totalΘ(n)

————————————————————

lines/efrequencystep sum
template < class T >000
void rank(T a[], int r[], int n)000
{000
for(int i = 0; i < n; ++i)1Θ(n)Θ(n)
{000
for(int j = i+1; j < n; ++j)1Θ(1+2+…+n)Θ(n2)
{000
if(a[i] <= a[j])1Θ(n2)Θ(n2)
++r[j];000
else1Ω(0), O(n2)Ω(0), O(n2)
++r[i];000
}000
}000
}000
totalΘ(n2)

————————————————————

lines/efrequencystep sum
template < class T >000
void permutation(T a[], int k, int m)000
{000
if(k == m)11Θ(1)
{000
for(int i = 0; i <= m; ++i)1m+2Θ(m)
cout << a[i] << " ";1m+1Θ(m)
cout << endl;11Θ(1)
}000
else1[0:1]Ω(0), O(1)
{000
for(int i = k; i <= m; ++i)1m-k+2Θ(m-k+2)
{000
swap(a[i], a[k]);1[0:m-k+1]Ω(0), O(m-k+1)
permutation(a, k+1, m);t(k+1, m)m-k(m-k)*t(k+1, m)
swap(a[i], a[k]);1[0:m-k+1]Ω(0), O(m-k+1)
}000
}000
}000

当k==m时,t(k,m) = Θ(m),
当k=0时
t(0,m) = mt(1, m)
= m
(m-1)*t(2, m)
= …
= m!t(m, m)
= Θ(m
m!)

1)其实很多人说permutaiton的复杂度时m!,其实也没错,这里是因为最后需要输出,而且输出的复杂度和输入m有关,所以最后的结果又在m!基础上乘了m
2)swap的复杂度没有计算,即使计算了,当m趋于无穷的时候,前面的所有量级比较小的阶乘,提取量级比较大的阶乘,变成阶乘倒数的和,极限为一个常数,亦可表示为Θ(m!)

函数

template <class T>
void permutation(T a[], int k, int m)
{
    if(k == m)
    {
        for(int i = 0; i <= m; ++i)
            cout << a[i] << " ";
        cout << endl;
    }
    else
    {
        for(int i = k; i <= m; ++i)
        {
            swap(a[i], a[k]);
            permutation(a, k+1, m);
            swap(a[i], a[k]);
        }
    }
}

应用举例

string array_d[] = {"l","o","v","e"};
    const int size_d = 4;
    permutation(array_d, 0, size_d-1);

————————————————————

带着大O怎么计算
呃当然带着O计算是不太可能了,因为O毕竟只是一个表示法。如果把它放在方程或公式中,它应该不带什么意义
不过,如果把大O中的g(n)放在公式中还是有意义的。

假如说某一步的结果为O(g(n)),或Θ(g(n)),那么如果下一步中需要用到这里的结果
1)用f(n),即取极限之前的函数,这样当然最准确
2)将g(n)抽象成带系数,带多项式的形式。
其一,这种方法主要是用于消除疑心,即使加上了系数以及其它项,但是由于在得到g(n)的结果的时候,其它项已经可以省略,因此在再计算的结果中应该也可以省略
其二,这种方法可以用于(当然还有1),因为1)最准确)n随着i变化然后求和或递推等等情况,比如(1+2+…+n)这种。
系数和其它项,可以在计算过程中或计算之前直接就省略了
3)直接用g(n)。即如果有很大把握是正确的,也可以直接用g(n)

不管用那种方法,我认为大O表示法的意义都在于,可以将比较起来渐近小于的项,在计算后,计算过程中,或计算之前,就省略掉。如2)其实是在计算过程中省略掉,3)是在计算过程之前就省略掉,1)当然则是在计算之后。如有涉及到变化的n,则可以将g(n)拿出来计算,再进行渐近比较

另外,也可以极度省略,即流行的大多数人的做法,直接拿更为抽象的过程作为一步,比如permutation的一次分形。或者某种排序中比较的次数,或如二分搜索的折半以及判断次数。虽然说这么做带有不精确的风险,但是应该可以论证,其结果是不受这种不精确的影响的。大概就是因为,这种关键的抽象步骤若代表输入n,那其步数基本上可以作为其系数,其它一些不重要的步骤可以作为多项式可以被忽略的项。不过似乎也没有人去论证过,然后大家也都这么用了。还是,大O表示法,以我之见,其精髓不仅在于如何表示,而且在于如何在计算过程的前中后省略(当然归根结底由其原理所得)。因此,理解其前因后果来龙去脉,还是很重要的。

————————————————————

lines/efrequencystep sum
template < class T >000
void selectionSort(T a[], int n)000
{000
for(int i = n-1; i > 0; --i)1nΘ(n)
{000
int iOfMax = indexOfMax(a, i+1);Θ(i)nΘ(n2)
swap(a[i], a[iOfMax]);1nΘ(n)
}000
}000
totalΘ(n2)
template <class T>
int indexOfMax(T a[], int n)
{
    if(n < 1) return -1;
    int index = 0;
    for(int i = 1; i < n; ++i)
    {
        if(a[index] < a[i])
            index = i;
    }
    return index;
}

————————————————————

lines/efrequencystep sum
template < class T >000
void selectionSort_stop(T a[], int n)000
{000
bool sorted = false;11Θ(1)
for(int i = n; !sorted && i > 1; --i)1nΘ(n)
{000
sorted = true;1Θ(n)Θ(n)
int indexOfMax = 0;1Θ(n)Θ(n)
for(int j = 1; j < i; ++j)1Θ(n2)Θ(n2)
{000
if(a[indexOfMax] < a[j]) indexOfMax = j;1Θ(n2)Θ(n2)
else sorted = false;1Ω(0), O(n2)Ω(0), O(n2)
}000
swap(a[indexOfMax], a[i-1]);1Θ(n)Θ(n)
}000
}00Θ(n2)

————————————————————

lines/efrequencystep sum
template < class T >000
void insert(T a[], int n, const T &x)000
{000
int i;11Θ(1)
for(i = n-1; i >= 0 && a[i] > x; --i)1Ω(1), O(n)Ω(1), O(n)
a[i+1] = a[i];1Ω(1), O(n)Ω(1), O(n)
a[i+1] = x;11Θ(1)
}000
000
totalΩ(1), O(n)
template < class T >000
void insertionSort(T a[], int n)000
{000
for(int i = 1; i < n-1; ++i)1Θ(n)Θ(n)
{000
T t = a[i];1Θ(n)Θ(n)
insert(a, i, t);Ω(1), O(n)Θ(n)Ω(n), O(n2)
}000
}000
totalΩ(n), O(n2)

这个是照着Sahni的答案写的。认识到的是Ω和O可以放在一起作为表示上下限并强调区间
————————————————————

lines/efrequencystep sum
template < class T >000
void insertionSort_2(T a[], int n)000
{000
for(int i = 1; i < n; ++i)1Θ(n)Θ(n)
{000
T t = a[i];1Θ(n)Θ(n)
int j;11Θ(1)
for(j = i-1; j >= 0 && a[j] > t; --j)1Ω(1), O(n)Ω(n), O(n2)
a[j+1] = a[j];1Ω(0), O(n)Ω(0), O(n2)
a[j+1] = t;1Θ(n)Θ(n)
}000
}000
totalΩ(n), O(n2)

————————————————————

lines/efrequencystep sum
template < class T >000
void bubble(T a[], int n)000
{000
for(int i = 0; i < n-1; ++i)1Θ(n)Θ(n)
if(a[i] > a[i+1]) swap(a[i], a[i+1]);1Θ(n)Θ(n)
}000
template < class T >000
void bubbleSort(T a[], int n)000
{000
for(int i = n; i > 1; --i)1Θ(n)Θ(n)
bubble(a, i);Θ(i)Θ(n)Θ(n2)
}000
totalΘ(n2)

————————————————————

lines/efrequencystep sum
template < class T >000
bool bubble_stop(T a[], int n)000
{000
bool swapped = false;11Θ(1)
for(int i = 0; i < n-1; ++i)1Θ(n)Θ(n)
{000
if(a[i] > a[i+1])1Θ(n)Θ(n)
{000
swap(a[i], a[i+1]);1Ω(0), O(n)Ω(0), O(n)
swapped = true;1Ω(0), O(n)Ω(0), O(n)
}000
}000
return swapped;11Θ(1)
}000
totalΘ(n)
template < class T >000
void bubbleSort_stop(T a[], int n)000
{000
for(int i = n; i > 1 && bubble_stop(a, i); --i);Θ(i)Θ(n)Θ(n2)
}000
totalΘ(n2)

————————————————————
参考 / 读书笔记读的书:
————————————————————

数据结构,算法与应用:C++语言描述(第二版)ISBN 978-7-111-49600-7

更新于
2021.04.06

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值