C语言关于时间复杂度详解

目录
  • 一、时间复杂度
    • 1.什么是时间复杂度?
    • 2.如何计算?
    • 3.常见的时间复杂度:
  • 二、空间复杂度
    • 1.什么是空间复杂度?
    • 2.如何计算?
  • 总结

一、时间复杂度

1.什么是时间复杂度?

空间效率,时间效率(较为关注)

时间复杂度:算法中的操作执行次数,为算法的时间复杂度。(不是具体时间,而是执行次数

2.如何计算?

时间复杂度

(1)是一个估算,看表达式中影响大的那一项,如N*N+2N+10中,N*N对整个式子影响最大,故其时间复杂度为N*N,用大O的渐近表示法O(N*N)。

(2)去掉时间表达式中的常数项乘积,例如,得到一个准确的时间表达式为2N+10,则估算得到的时间复杂度为O(N)

(3)对于多个未知数时,例如时间表达式为N+M,假设M,N差不多大,则O(M)或O(N);假设M远大于N,则O(M)。

(4)用常数1去替代所有确定的常数,如准确的时间表达式为100,O(1).

(5)未知数和常数,滤去常数。

(6)另外有些算法分为最好,最坏,平均这三种情况。当算法存在这三种情况时,选最坏的时间复杂度,例如假设字符串长度为N,“sdsfrsgtr...”,遍历字符串,求S的时间复杂度,最好O(1),最坏O(N),平均O(N/2)。

A.  在冒泡排序中,

第一趟冒泡:N

第二趟冒泡:N-1

第三趟冒泡:N-2

第N趟冒泡:1

为等差数列,准确次数为:        N*(N+1)/2

冒泡排序时间复杂度为O(N*N)

B.  在二分查找/折半查找中:

假设二分了X次,有1*2*2....*2=N,2^X=N, X=(log2) N

算法的复杂度计算中,喜欢省略成logN,因为不好写底数,但是写成lg N,是错的。

C.  在某些阶乘的运算中求时间复杂度:

long long Factorial(size_t N)
{
   return N<2 ? N:Factorial(N-1)*N;
}

如Factorial(10),则返回factorial(9)*10,在返回到factorial(9)*8.....以此类推返回到

factorial(1)*2返回到1.(实际是10!)递归了N次,故时间复杂度为O(N)。(特别注意:结返回结果是N!,但是操作的次数是递归了N次,所以时间复杂度为O(N))

3.常见的时间复杂度:

 二、空间复杂度

1.什么是空间复杂度?

空间复杂度是算法运行过程中临时占用存储空间大小的量度,不在意其具体占了多少比特的大小,而是计算变量的个数。

2.如何计算?

对照时间复杂度的计算方法。注意:时间是累积的,空间是不累计的,空间可以销毁。

例题1:消失的数字

思路1:排序 0 1 2 3 4 5 6 7 9 一次比较,若下一个数与上一个数只差为1,则掠过,若下一个数比上一个数>1,则找到,但时间复杂度不符合。

思路2:把0到N加到一起,结果ret1,再把数组中的数加到一起ret2,ret1-ret2就是要找的数。

思路3:异或:相同为0,相异为1。将数组中的数与0-N数互相异或,最后剩下的那个数字就是缺的那个数。

int missingNumber(int* nums, int numsSize){
    int x=0;
    //先和数组的数进行异或
    for(int i=0;i<numsSize;++i)
    {
        x^=nums[i];
    }
    //在和0-N的数进行异或
    for(int j=0;j<numsSize+1;++j)
    {
        x^=j;
    }
return x;
}

要注意0-N数异或时,注意j<numsSize+1,它比原数组中元素个数多1。

 例题2:旋转数组

思路1:保存最后一个数,将其挪到前面来。k次

void rotate(int* nums, int numsSize, int k){
    for(int i=0;i<k;++i)
    {
    int tmp=nums[numsSize -1];
    for(int end=numsSize -2;end >=0;--end)
    {
        nums[end+1]=nums[end];
    }
    nums[0]=tmp;
    }
}

但此时时间复杂度为O(N*K),跑不过~

思路2:以空间换时间,尝试着多消耗一点空间,一次换成。将后K个保存,移到前面来,直接得到。时间复杂度为O(N),空间复杂度为O(N)

思路3:后K个逆置,前K个逆置,整体逆置(这个实在是太牛了!!)

c代码为:

//逆置
void Reverse(int *nums ,int left,int right){
    while(left<right)
    {
        int tmp=nums[left];
        nums[left]=nums[right];
        nums[right]=tmp;
        ++left;
        --right;
    }
}
void rotate(int* nums, int numsSize, int k)
{
    //控制好下标,后N-K个
    Reverse(nums,numsSize-k,numsSize-1);
    Reverse(nums,0,numsSize-k-1);
    Reverse(nums,0,numsSize-1);

}

注意结果可能出错:

此时需要注意K是否大于N,当K>N时需要取模:k%=numsSize

添加:if(K>numsSize){ K%numsSize;}

//逆置
void Reverse(int *nums ,int left,int right){
    while(left<right)
    {
        int tmp=nums[left];
        nums[left]=nums[right];
        nums[right]=tmp;
        ++left;
        --right;
    }
}
void rotate(int* nums, int numsSize, int k)
{
    if(k>numsSize)
    {
        k%=numsSize;
    }
    //控制好下标,后N-K个
    Reverse(nums,numsSize-k,numsSize-1);
    Reverse(nums,0,numsSize-k-1);
    Reverse(nums,0,numsSize-1);

}

在力扣上运行得到:

总结

到此这篇关于C语言关于时间复杂度详解的文章就介绍到这了,更多相关C语言时间复杂度内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • C语言数据结构时间复杂度及空间复杂度简要分析

    目录 一.时间复杂度和空间复杂度是什么? 1.1算法效率定义 1.2时间复杂度概念 1.3空间复杂度概念 二.如何计算常见算法的时间复杂度和空间复杂度 2.1时间复杂度计算 2.2空间复杂度计算 2.3快速推倒大O渐进表达法 三.一些特殊的情况 总结 一.时间复杂度和空间复杂度是什么? 1.1算法效率定义 算法效率分为两种,一种是时间效率--时间复杂度,另一种是空间效率--空间复杂度 1.2时间复杂度概念 时间复杂度,简言之就是你写一个代码,它解决一个问题上需要走多少步骤,需要花费多长时间.打个

  • C语言关于时间复杂度详解

    目录 一.时间复杂度 1.什么是时间复杂度? 2.如何计算? 3.常见的时间复杂度: 二.空间复杂度 1.什么是空间复杂度? 2.如何计算? 总结 一.时间复杂度 1.什么是时间复杂度? 空间效率,时间效率(较为关注) 时间复杂度:算法中的操作执行次数,为算法的时间复杂度.(不是具体时间,而是执行次数) 2.如何计算? 时间复杂度 (1)是一个估算,看表达式中影响大的那一项,如N*N+2N+10中,N*N对整个式子影响最大,故其时间复杂度为N*N,用大O的渐近表示法O(N*N). (2)去掉时间

  • C语言之平衡二叉树详解

    目录 什么是平衡二叉树 平衡二叉树的基本特点 为什么会出现平衡二叉树 二叉树四种不平衡的情况 C语言实现平衡二叉树 什么是平衡二叉树 平衡二叉树是具有平衡属性的有序二叉树,所谓的平衡即当前树的左右子树高度差的绝对值不超过1.因为平衡二叉树是由苏联数学家Adelson-Velskii和Landis提出,所以又称为AVL树. 平衡二叉树的基本特点 是特殊的有序二叉树 左右子树高度差的绝对值不超过1 左右子树仍然是平衡二叉树 为什么会出现平衡二叉树 在学习平衡二叉树之前必定已经学过有序二叉树,有序二叉

  • 易语言子程序知识点详解

    将程序分割成较小的逻辑组件就可以简化程序设计任务,这些逻辑组件被称为子程序. 子程序可用于压缩重复任务或共享任务,例如,压缩频繁的计算处理等等. 用子程序编程有两大好处: 子程序可使程序划分成离散的逻辑组件,每个组件都比无子程序的整个程序容易调试及理解: 一个应用程序中的子程序,往往不必修改或只需稍作改动,便可以成为另一个程序的子程序. 每次调用子程序时,子程序中的所有语句都将被从第一条开始顺序执行,当执行到子程序尾部或者遇到"返回"命令时即返回到调用此子程序语句的下一条语句处. 子程

  • Spring表达式语言SpEL用法详解

    这篇文章主要介绍了spring表达式语言SpEL用法详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 (1)spring表达式语言是一个支持运行时查询和操作对象图得我强大表达式语言. (2)语言类似于EL:SpEL使用#{...}作为定界符.所有在大括号中的字符串均被认为是SpEL. (3)SpEL为bean的属性进行动态赋值提供了便利. (4)通过SpEL可以实现: 通过Bean的id对Bean进行引用 调用方法及引用对象的属性 计算表达式

  • R语言数据类型深入详解

    R语言用来存储数据的对象包括: 向量, 因子, 数组, 矩阵, 数据框, 时间序列(ts)以及列表 意义介绍 1. 向量(一维数据): 只能存放同一类型的数据 语法: c(data1, data2, ...),访问的时候下标从1开始(和Matlab相同);向量里面只能存放相同类型的数据. > x <- c(1,5,8,9,1,2,5) > x [1] 1 5 8 9 1 2 5 > y <- c(1,"zhao") # 这里面有integer和字符串, 整

  • R语言关联规则深入详解

    在用R语言做关联规则分析之前,我们先了解下关联规则的相关定义和解释. 关联规则的用途是从数据背后发现事物之间可能存在的关联或者联系,是无监督的机器学习方法,用于知识发现,而非预测. 关联规则挖掘过程主要包含两个阶段:第一阶段从资料集合中找出所有的高频项目组,第二阶段再由这些高频项目组中产生关联规则. 接下来,我们了解下关联规则的两个主要参数:支持度和置信度. 用简化的方式来理解这两个指标,支持度是两个关联物品同时出现的概率,而置信度是当一物品出现,则另一个物品也出现的概率. 假如有一条规则:牛肉

  • R语言“循环”知识点详解

    可能有一种情况,当你需要执行一段代码几次. 通常,顺序执行语句. 首先执行函数中的第一个语句,然后执行第二个语句,依此类推. 编程语言提供允许更复杂的执行路径的各种控制结构. 循环语句允许我们多次执行一个语句或一组语句,以下是大多数编程语言中循环语句的一般形式 - R编程语言提供以下种类的循环来处理循环需求. 单击以下链接以检查其详细信息. Sr.No. 循环类型和描述 1 repeat循环 多次执行一系列语句,并简化管理循环变量的代码. 2 while循环 在给定条件为真时,重复语句或语句组.

  • C语言字符串数组详解

    C语言字符串数组 字符串是连续的字符序列,最后以空字符'\0'作为终止符.一个字符串的长度指所有字符的数量,但不包括终止符.在 C 语言中,没有字符串类型,自然也就没有运算符以字符串为操作数. 字符串被存储在元素类型为 char 或宽字符类型数组中(宽字符类型指 wchar_t.char16_t 或 char32_t).宽字符组成的字符串也称为宽字符串(wide string). C 标准库提供了大量的函数,它们可以对字符串进行基本操作,例如字符串的比较.复制和连接等.在这些传统的字符串函数以外

  • C语言lseek()函数详解

     头文件: #include <sys/types.h> #include <unistd.h> 函数原型: off_t lseek(int fd, off_t offset, int whence);//打开一个文件的下一次读写的开始位置 参数: fd 表示要操作的文件描述符 offset是相对于whence(基准)的偏移量 whence 可以是SEEK_SET(文件指针开始),SEEK_CUR(文件指针当前位置) ,SEEK_END为文件指针尾 返回值: 文件读写指针距文件开头

  • 关于C语言qsort函数详解

    目录 C语言qsort函数详解 一.qsort函数是什么 二.使用qsort排序-以升序为例 1.整形数组排序 2.字符数组排序 3.字符指针数组排序 4.结构体数组排序 5.浮点型数组排序 三.使用冒泡排序思想模拟实现qsort函数 1.什么是冒泡排序 2.冒泡排序代码 3. 使用冒泡排序思想模拟实现qsort函数 C语言qsort函数详解 一.qsort函数是什么 我们可以使用  搜索库函数网址或者MSDN软件进行查找. qsort()函数:快速排序的函数  -引用stdlib.h头文件 参

随机推荐