C语言关于时间复杂度详解
作者:爽爽不会编程 发布时间:2022-08-14 02:33:04
一、时间复杂度
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);
}
在力扣上运行得到:
来源:https://blog.csdn.net/weixin_47754029/article/details/122349694


猜你喜欢
- 这篇文章主要介绍了dotnet core链接mongodb代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价
- 本文实例为大家分享了Android刮刮卡效果,供大家参考,具体内容如下android实现底层一张图片,上层一个遮罩层,触摸滑动按手指滑动路径
- 本人工作有一个月多了。对于android很多东西,都有了新的了解或者说真正的掌握。为了让更多的像我这样的小白少走弯路,所以我会坚持将我在工作
- Java中方法重写与重载的区别重 写重 载子类方法对父类方法的覆盖同一个类中同名方法的重载(同一类包括从父类继承的方法)方法名相同且参数个数
- 传统的多分支方式(圈复杂度为6):public String order(String type) { if ("1&
- 一、何为栈?栈(stack)又名堆栈,它是一种运算受限的线性表。限定仅在表尾进行插入和删除操作的线性表。这一端被称为栈顶,相对地,把另一端称
- 前两天,谷歌发布了Android Studio 1.0的正式版,也有更多的人开始迁移到Android Studio进行开发。然而,网上很多的
- 在很多语音视频软件系统中,经常有将实时的音频或视频录制为文件保存到磁盘的需求,比如,视频监控系统中录制监控到的视频、视频会议系统中录制整个会
- 今天深度学习一下《Java并发编程的艺术》的第1章并发编程的挑战,深入理解Java多线程,看看多线程中的坑。注意,哈肯的程序员读书笔记并不是
- 简介在实现登录功能时,一般为了安全都会设置验证码登录,为了防止某个用户用特定的程序暴力破解方式进行不断的尝试登录。常见验证码分为图片验证码和
- Java作为一面向对象的语言,具备面向对象的三大特征——继承,多态,封装。继承顾名思义,继任,承接,传承的意思。面向对象的语言有一个好处,就
- 本文实例为大家分享了Unity实现每日签到系统的具体代码,供大家参考,具体内容如下代码:using System;using System.
- 最近把以前制作的截图程序重新写了一下动了一个大手术 高质量仿照的TX的截图程序先看几个效果图拖动过程中显示当前鼠标下一小块的图像信息 尺寸、
- 这篇文章主要介绍了Spring JDK * 实现过程详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要
- Quick Start在SpringBoot中使用log4j2日志框架,只需三步:引入依赖配置log文件获取Logger实例并输出日志引入依
- ManualResetEvent表示线程同步事件,可以对所有进行等待的线程进行统一管理(收到信号时必须手动重置该事件)其构造函数为:publ
- 在国际化环境下,越来越多的程序需要做多语言版本,以适应各种业务需求的变化。在Winform应用程序中实现多语言也有常规的处理方式处理,不过需
- 下面就为大家带来3种比较常见的压缩方式先给出一组数据原图:width:2976; height:2976原图实际:--->byte:2
- 本文实例为大家分享了SpringBoot使用POI进行Excel下载的具体代码,供大家参考,具体内容如下使用poi处理Excel特别方便,此
- 使用可以绑定数据源的控件我们需要有实现了IList接口的类作为数据源,我们有很多的方法,比如使用ArrayList或者List的泛型类都是很