算法的时间复杂度

简介: 算法的时间复杂度

⭐算法效率

如何衡量一个算法的好坏?

算法在编写成可执行程序后,运行时需要耗费时间资源和空间(内存)资源 。因此衡量一个算法的好坏,一般是从时间空间两个维度来衡量的,即时间复杂度空间复杂度

⭐时间复杂度

一个程序的运行,依赖于其本身的算法设计以及不同的机器性能。单纯地只是从计算其运算时间的角度来评估一个算法是不合理的。

因此引进了时间复杂度

🌟时间复杂度

时间复杂度主要衡量一个算法的运行快慢,而空间复杂度主要衡量一个算法运行所需要的额外空间。

在计算机发展的早期,计算机的存储容量很小。所以对空间复杂度很是在乎。但是经过计算机行业的迅速发展,计算机的存储容量已经达到了很高的程度。所以我们如今已经不需要再特别关注一个算法的空间复杂度,更关注一个算法的时间复杂度。

🐟时间复杂度的概念

一个算法所花费的时间与其中语句的执行次数成正比例。算法中的基本操作的执行次数,为算法的时间复杂度

🐳例1

// 请计算一下Func1中++count语句总共执行了多少次?
void Func1(int N)
{
    int count = 0;
    for (int i = 0; i < N ; ++ i)
    {
         for (int j = 0; j < N ; ++ j)
        {
             ++count;
         }
    }
    for (int k = 0; k < 2 * N ; ++ k)
    {
         ++count;
    }
    int M = 10;
    while (M--)
    {
         ++count;
    }
    printf("%d\n", count);
}

Func1执行的基本操作次数

F(N)=N^2+2N+10

但实际上当N非常大时,最高数量级的N^2对F(N)会起到决定性影响。

并且在实际中,我们其实并不一定要计算精确的执行次数,而只需要大概执行次数,那么这里我们使用大O的渐进表示法

🐟大O的渐进表示法

大O符号(Big O notation):是用于描述函数渐进行为的数学符号。

推导大O阶方法:
1、用常数1取代运行时间中的所有加法常数
2、在修改后的运行次数函数中,只保留最高阶项

3、如果最高阶项存在且不是1,则去除与这个项目相乘的常数。得到的结果就是大O阶。

🐳 例2

// 计算Func2的时间复杂度?
void Func2(int N)
{
     int count = 0;
     for (int k = 0; k < 2 * N ; ++ k)
     {
         ++count;
     }
     int M = 10;
     while (M--)
     {
         ++count;
     }
     printf("%d\n", count);
}

具体的执行次数F(N)=2N+10

我们只需要抓大头,for循环这条语句是最主要的。

因此Func2的时间复杂度为O(N)

🐳例3

// 计算Func3的时间复杂度?
void Func3(int N, int M)
{
     int count = 0;
     for (int k = 0; k < M; ++ k)
     {
         ++count;
     }
     for (int k = 0; k < N ; ++ k)
    {
        ++count;
    }
    printf("%d\n", count);
}

Func3函数中,M和N是两个未知数。

当M>>N时,算法的时间复杂度为:O(M)

当N>>M时,算法的时间复杂度为: O(N)

当M=N时,算法的时间复杂度为O(M)或者O(N)

但由于我们不清楚M和N的具体关系,因此这个算法的时间复杂度为:O(M+N)更准确。

🐳例4

// 计算Func4的时间复杂度?
void Func4(int N)
{
    int count = 0;
    for (int k = 0; k < 100; ++ k)
    {
        ++count;
    }
    printf("%d\n", count);
}

Func4是可以清楚地知道for语句语句会执行100次,因此这个算法的时间复杂度为O(1)

🐳例5

// 计算Func5的时间复杂度?
void Func4(int N)
{
    int count = 0;
    for (int k = 0; k < 1000000; ++ k)
    {
        ++count;
    }
    printf("%d\n", count);
}

如果这里换成1000,000实际上算法的时间复杂度还是O(1)。

这主要依赖于CPU的强大。CPU的运算速度是十分快的。

这是由于此,对于CPU而言,运行100和1000,1000000 语句,其时间都是一样的。

🐳例6

// 计算strchr的时间复杂度?
const char * strchr ( const char * str, int character );

这个库函数表示,在字符串s中查找字符c,返回字符c第一次在字符s中出现的位置,如果未找到字符c,则返回NULL。

这个需要分情况讨论。

比如说,调用这个函数,并传递参数,字符串"hello,world"。

最好的情况是,查找的字符,我们传递的是字符"h",那么这样就只进行了1次查找。

最坏的情况是,查找的字符,我们传递的参数是"d"那么这样就遍历了一次字符数组11次才查找到。或者我们传递的参数是"a",遍历了数组,没有查找到。

平均情况是,11/2=5次

在这种情况中我们关注的是算法最坏的情况。

另外有些算法的时间复杂度存在最好、平均和最坏情况:
最坏情况:任意输入规模的最大运行次数(上界)
平均情况:任意输入规模的期望运行次数

最好情况:任意输入规模的最小运行次数(下界) 例如:在一个长度为N数组中搜索一个数据x
在实际中一般情况关注的是算法的最坏运行情况,所以数组中搜索数据时间复杂度为O(N)

🐳例7

// 计算BubbleSort的时间复杂度?
void BubbleSort(int* a, int n)
{
    assert(a);
    for (size_t end = n; end > 0; --end)
    {
        int exchange = 0;
        for (size_t i = 1; i < end; ++i)
        {
        if (a[i-1] > a[i])
        {
            Swap(&a[i-1], &a[i]);
            exchange = 1;
        }
        }
        if (exchange == 0)
        break;
    }
}

这个算法是冒泡排序。

冒泡排序,是两个相邻元素进行比较,交换;重复这个过程,将最大(重)的沉下去。重复上述,将第二大再沉下去。…

最好情况是,无需进行交换。

最坏情况是,假如有n个数。

第一次交换为n-1次。

第二次交换为n-2次。

第三次交换为n-3次。

第n-1次交换为1次

所以总次数为

为(n-1)+(n-2)+(n-3)+…+1=[(n-1)+1]*(n-1)/2=n(n-1)/2次。

故冒泡算法的时间复杂度为

O(N^2)

相关文章
|
2月前
|
机器学习/深度学习 存储 缓存
数据结构从入门到精通——算法的时间复杂度和空间复杂度
算法的时间复杂度和空间复杂度是评估算法性能的两个重要指标。时间复杂度主要关注算法执行过程中所需的时间随输入规模的变化情况,而空间复杂度则关注算法执行过程中所需的最大存储空间或内存空间。
77 0
|
4月前
|
机器学习/深度学习 存储 算法
数据结构 | 算法的时间复杂度和空间复杂度【详解】(二)
数据结构 | 算法的时间复杂度和空间复杂度【详解】(二)
|
4月前
|
机器学习/深度学习 存储 算法
数据结构 | 算法的时间复杂度和空间复杂度【详解】(一)
什么是数据结构? 数据结构(Data Structure)是计算机存储、组织数据的方式,指相互之间存在一种或多种特定关系的数据元素的集合。
|
4月前
|
机器学习/深度学习 算法
算法的时间复杂度
算法的时间复杂度
41 0
|
5月前
|
机器学习/深度学习 存储 算法
【算法基础】常数操作 时间复杂度 选择排序 冒泡排序 插入排序 位运算
【算法基础】常数操作 时间复杂度 选择排序 冒泡排序 插入排序 位运算
|
6月前
|
机器学习/深度学习 算法
数据结构与算法之时间复杂度和空间复杂度(C语言版)
数据结构与算法之时间复杂度和空间复杂度(C语言版)
数据结构与算法之时间复杂度和空间复杂度(C语言版)
|
5月前
|
算法 Python
Python 数据结构和算法:解释什么是 Big O 表示法?举例说明几种常见的时间复杂度。
Python 数据结构和算法:解释什么是 Big O 表示法?举例说明几种常见的时间复杂度。
|
1月前
|
算法 数据处理 C语言
【数据结构与算法】快速排序(详解:快排的Hoare原版,挖坑法和双指针法|避免快排最坏时间复杂度的两种解决方案|小区间优化|非递归的快排)
【数据结构与算法】快速排序(详解:快排的Hoare原版,挖坑法和双指针法|避免快排最坏时间复杂度的两种解决方案|小区间优化|非递归的快排)
|
2月前
|
算法
TOP-K问题和向上调整算法和向下调整算法的时间复杂度问题的分析
TOP-K问题和向上调整算法和向下调整算法的时间复杂度问题的分析
20 1
|
2月前
|
机器学习/深度学习 存储 缓存
数据结构--算法的时间复杂度和空间复杂度
数据结构--算法的时间复杂度和空间复杂度