#01算法的复杂性

news2024/12/23 19:41:44

时间复杂度

public void print(int n){
    int a = 1; //执行1次
    for(int i=0;i<n;++i){//执行n次
        System.out.println(a+i);//执行n次
    }
}

该算法的时间复杂度是O(2n+1)  大O会忽略常数、低阶和系数,最终记作O(n); 如果算法的执行时间和数据规模n无关,则是常量阶,记作O(1);

一般情况下,只要算法中不存在循环语句、递归语句,即使有成千上万行的代码,其时间复杂度也是Ο(1)

指数和阶乘是非多项式量级,其余都是多项式量级。我们把时间复杂度是非多项式量级的算法问题称为NP(Non-Deterministic-Polynomial,非确定多项式)问题。

//n是数组nums的长度
public int find(int[]nums,int n,int target){
    for(int i=0;i<n;++i){
        if(nums[i]==target){
            return i;
        }
    }
    return -1;
}

最好情况:上边最理想的情况就是第一个就是要找的,所以最好情况下时间复杂度是O(1)

最坏情况:最坏的情况,就是要找的数在最后一个,需要遍历n次,最坏情况下时间复杂度是O(n

平均时间复杂度:为了方便说明,我们假设数组中一定存在要找的数。而要找的数在0 - n-1这些位置出现的概率相同,都是 1/n ,所以考虑每种情况下总共要查找的次数,求出总数,然后再除以 可能的情况数,就是平均要查找的次数:

去除常量和系数就是:O(n) ;

    public int[] twoSum(int[] nums, int target) {
        //初始化一个数组存放结果
        int[] re =new int[2];
        for(int i=0;i<nums.length-1;++i){
            int num1 = nums[i];
            for(int j=i+1;j<nums.length;++j){
                int nums2=nums[j];
                //如果找到,就返回结果,避免多余循环
                if((num1+nums2)==target){
                    re[0] = i;
                    re[1] = j;
                    return re;
                }
            }
        }
        return re;
    }

最好情况:最好情况就是我们要找的两个数,刚好就是第一个和第二个数。所以外循环循环一次,内循环循环一次就完成了查找。时间复杂度是:O ( 1 ) ;

最坏情况:最坏情况就是,找遍到最后一个元素,才找到。

  • 外层循环是从0循环到n-2
  • 内层循环和外层循环的值有关,从外层当前的值,循环到n-1

总的比较次数就是每个外层循环时,内层循环的次数之和。比如外层i=0时,内层从1循环到n-1循环了n-1次,外层i=1时,内层从2循环到n-1循环了n-2次 …直到最后一次,内层只需要循环1次...

 去掉常量、系数和低阶,时间复杂度就是: O(n^{2}) ;

平均情况 : 

 分析:我们最终的目的是要找到两个数,满足我们的条件。代码的外层循环显然是找第一个数,内层循环在找第二个数。根据假设,这对数存在并且唯一。(其他情况,比如有重复,复杂度会介于最好和平均之间,因为更容易找到,所以这里我们只分析唯一的情况)我们假设第一个要找的数 出现在下标 0 - n -2 的概率相等,都是 1/(n-2) , 所以外层循环的次数可能出现的情况如下:

当外层循环的次数是 1/(n-2) 时,内层需要循环n-1次,因为内层循环次数和外层的当前i有关。所以加权平均情况下的总的比较次数就是:

分子和分母的n-1 与n-2可以近似约掉,最后去掉系数和低阶 所以最终结果就是: O(n^{2}) ;

int i = 1;
while(i<n)
{
    i = i * 2;
}

在while循环里面,每次都将 i 乘以 2,乘完之后,i 距离 n 就越来越近了。我们试着求解一下,假设循环x次之后,i 就大于 2 了,此时这个循环就退出了,也就是说 2 的 x 次方等于 n,那么 x = log2^n
也就是说当循环 log2^n 次以后,这个代码就结束了。因此这个代码的时间复杂度为:O(logn) 

计算时间复杂度

例1
//计算Func1的时间复杂度
void Func1(int N)
{
	int count = 0;
	for (int i = 0; i < 2 * N; i++)
	{
		for (int j = 0; j < 2 * N; j++)
		{
			count++;
		}
	}
	for (int k = 0; k < 2 * N; k++)
	{
		count++;
	}
}

所以Func1函数的时间复杂度为:T(N) = 4 * N^{2} + 2 * N ;大O的渐进表示法,只保留最高阶项(即4 * N^{2}),去除最高项的系数后(即N^{2})。所以,用大O的渐进表示法表示Func1函数的时间复杂度为:O(N^{2}) 。

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

Func2函数的时间复杂度为T(N) = 100 ;根据大O的渐进表示法,所有的常数都用常数1来表示,所以,用大O的渐进表示法表示Func2函数的时间复杂度为:O(1) ;

例3
//计算二分查找函数的时间复杂度
int BinarySearch(int* a, int N, int x)
{
	assert(a);
	int begin = 0;
	int end = N - 1;
	while (begin < end)
	{
		int mid = begin + ((end - begin) >> 1);
		if (x > a[mid])
			begin = mid + 1;
		else if (x < a[mid])
			end = mid - 1;
		else
			return mid;
	}
	return -1;
}

计算二分查找函数的时间复杂度,我们需要对代码进行分析:我们用二分查找法查找数据时,查找一次后可以筛去一半的数据,经过一次次的筛选,最后会使得待查数据只剩一个,那么我们查找的次数就是while循环执行的次数。
因为数据个数为N,一次查找筛去一半的数据,即还剩N/2个数据,经过一次次的筛选,数据最后剩下1个,那么查找的次数可以理解为N除以若干个2,最后得1,那么while循环执行的次数就是N除以2的次数,我们只需计算N除以了多少次2最终等于1即可。

我们假设N除以了x个2,最终等于1,那么

最后,两边同时取2的对数,得while循环执行的次数,即x = logN 。所以,用大O的渐进表示法表示二分查找函数的时间复杂度为:O(logN) 

表示时间和空间复杂度时,log表示以2为底的对数。

例4
//计算斐波那契函数的时间复杂度
int Fibonacci1(int N)
{
	if (N == 0||N == 1)
		return 1;
	else
		return Fibonacci1(N - 1) + Fibonacci1(N - 2);
}

使用递归法求斐波那契数,当我们要求某一个斐波那契数时,需要知道他的前两个斐波那契数,然后相加得出。那么当我们要知道第N个斐波那契数时,递归的次数如下图:

因为右下角的递归函数会提前结束,所以图中三角形必定有一块是没有数据的,但是当N趋于无穷时,那缺省的一小块便可以忽略不计,这时总共调用斐波那契函数的次数为:

等比数列的求和,最后得出结果为:2^{N} - 1 。
保留最高阶项后,用大O的渐进表示法表示斐波那契函数的时间复杂度为:O(2^{N})

注:递归算法的时间复杂度 = 递归的次数 * 每次递归函数中的次数。

//注意:斐波那契数列自顶向下递归的时间复杂度是2的n次方/(1.618的n次方);空间复杂度是O(n) ;  自底向上保留子问题的值求解时间复杂性是O(n),空间复杂度也是O(n);


空间复杂度

O(1)

一个算法的空间复杂度(Space Complexity)S(n)定义为该算法所耗费的存储空间,它也是问题规模n的函数。渐近空间复杂度也常常简称为空间复杂度。空间复杂度算的是变量的个数

如果算法执行所需要的临时空间不随着某个变量n的大小而变化,即此算法空间复杂度为一个常量,可表示为 O(1)

int i = 1;
int j = 2;
++i;
j++;
int m = i + j;
//代码中的 i、j、m 所分配的空间都不随着处理数据量变化,因此它的空间复杂度S(n) = O(1)
 O(n)
int[] m = new int[n]
for(i=1; i<=n; ++i)
{
   j = i;
   j++;
}

第一行new了一个数组出来,这个数据占用的大小为n,这段代码的2-6行,虽然有循环,但没有再分配新的空间,因此,这段代码的空间复杂度主要看第一行即可,即 S(n) = O(n)

例1
//计算冒泡排序函数的空间复杂度
void BubbleSort(int* a, int N)
{
	assert(a);
	for (int i = 0; i < N; i++)
	{
		int exchange = 0;
		for (int j = 0; j < N - 1 - i; j++)
		{
			if (a[j]>a[j + 1])
			{
				int tmp = a[j];
				a[j] = a[j + 1];
				a[j + 1] = tmp;
				exchange = 1;
			}
		}
		if (exchange == 0)
			break;
	}
}

冒泡排序函数中使用了常数个额外空间(即常数个变量),所以用大O的渐进表示法表示冒泡排序函数的空间复杂度为O(1)

例2
//计算阶乘递归函数的空间复杂度
long long Factorial(size_t N)
{
	return N < 2 ? N : Factorial(N - 1)*N;
}

阶乘递归函数会依次调用Factorial(N),Factorial(N-1),…,Factorial(2),Factorial(1),开辟了N个空间,所以空间复杂度为O(N)

注:递归算法的空间复杂度通常是递归的深度(即递归多少层)。

例3

斐波那契数列的空间复杂性为O(n);

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1865341.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

PR曲线(Precision-Recall Curve,精确率-召回率曲线)

PR曲线&#xff08;Precision-Recall Curve&#xff0c;精确率-召回率曲线&#xff09;是一种用于评估二分类模型性能的工具&#xff0c;特别适用于不平衡数据集。PR曲线通过绘制精确率&#xff08;Precision&#xff09;与召回率&#xff08;Recall&#xff09;之间的关系&…

Unity射击游戏开发教程:(30)如何让玩家追踪敌人

在本文中,我将介绍如何让敌人旋转跟随玩家并以相同的旋转发射射弹。我追求的行为是…… 当玩家移动时,敌人会旋转,因此它始终指向玩家。敌人将以恒定的速率发射射弹,并且射弹将以与敌人发射时相同的位置和旋转开始。

智能聊天AI机器人网页怎么聊?这样做很简单

智能聊天AI机器人网页怎么聊&#xff1f;随着科技的飞速发展&#xff0c;智能聊天AI机器人已经逐渐渗透到我们的日常生活中&#xff0c;为我们提供了更加便捷、高效的交流方式。在网页上&#xff0c;这些智能聊天机器人以其独特的魅力&#xff0c;为我们打开了与机器对话的新世…

Java数据脱敏

数据脱敏 敏感数据在存储过程中为是否为明文, 分为两种 落地脱敏: 存储的都是明文, 返回之前做脱敏处理不落地脱敏: 存储前就脱敏, 使用时解密, 即用户数据进入系统, 脱敏存储到数据库中, 查询时反向解密 落地脱敏 这里指的是数据库中存储的是明文数据, 返回给前端的时候脱…

# [0622] Task02 model-free 免模型类 RL 算法的预测和控制 【ε 贪心策略 优化的证明】

easy-rl PDF版本 笔记整理 P3 joyrl 比对 补充 P4 - P5 相关 代码 整理 ——> 有空 另开一页 最新版PDF下载 地址&#xff1a;https://github.com/datawhalechina/easy-rl/releases 国内地址(推荐国内读者使用)&#xff1a; 链接: https://pan.baidu.com/s/1isqQnpVRWbb3yh8…

Keka for Mac:轻量级压缩解压神器

Keka for Mac是一款专为Mac用户打造的轻量级压缩解压软件&#xff0c;凭借其强大的功能和简洁易用的界面&#xff0c;赢得了众多用户的喜爱。无论是日常办公还是学习娱乐&#xff0c;Keka都能为您提供高效、安全的文件压缩和解压体验。 Keka for Mac v1.4.2中文版下载 产品特点…

NAT和内网穿透

NAT&#xff08;Network Address Translation&#xff0c;网络地址转换&#xff09;是一种广泛应用于计算机网络的技术&#xff0c;其主要目的是为了解决IPv4地址空间的短缺问题&#xff0c;并且增强网络安全。NAT技术允许一个私有网络内的多个设备共享一个或几个全局唯一的公共…

JavaEE之HTTP协议(1)_HTTP基础知识,HTTP 请求、响应格式,方法,状态码

一、HTTP协议 1.1 基本概念: HTTP全称超文本传输协议&#xff0c;是一种无状态的、应用层的协议&#xff0c;它基于请求/响应模型。客户端&#xff08;通常是Web浏览器&#xff09;通过发送HTTP请求到服务器来获取或发送信息&#xff0c;服务器则返回HTTP响应作为回应。HTTP协…

MySQL实训--原神数据库

原神数据库 er图DDL/DML语句查询语句存储过程/触发器 er图 DDL/DML语句 SET NAMES utf8mb4; SET FOREIGN_KEY_CHECKS 0;DROP TABLE IF EXISTS artifacts; CREATE TABLE artifacts (id int NOT NULL AUTO_INCREMENT,artifacts_name varchar(255) CHARACTER SET utf8 COLLATE …

宿主机无法通过ip连接wsl2解决方案

文章目录 原因排查网络模式win11防火墙关闭wsl ubuntu防火墙 如果之前能连接现在连接不上可以参考该方案 原因排查 网络模式win11防火墙(win11新增了Hyper-V防火墙)wsl2 ubuntu防火墙 网络模式 wsl2的默认网络模式是NAT&#xff0c;建议修改为镜像模式。在C:\Users\<User…

深入探讨极限编程(XP):技术实践与频繁发布的艺术

目录 前言1. 极限编程的核心原则1.1 沟通1.2 简单1.3 反馈1.4 勇气1.5 尊重 2. 关键实践2.1 结对编程2.1.1 提高代码质量2.1.2 促进知识共享2.1.3 增强团队协作 2.2 测试驱动开发&#xff08;TDD&#xff09;2.2.1 提升代码可靠性2.2.2 提高代码可维护性2.2.3 鼓励良好设计 2.3…

Volatility 内存取证【信安比赛快速入门】

一、练习基本命令使用 1、获取镜像信息 ./volatility -f Challenge.raw imageinfo 一般取第一个就可以了 2、查看用户 ./volatility -f Challenge.raw --profileWin7SP1x64 printkey -K "SAM\Domains\Account\Users\Names" 3、获取主机名 ./volatility -f Challenge…

【学习】使用PyTorch训练与评估自己的ResNet网络教程

参考&#xff1a;保姆级使用PyTorch训练与评估自己的ResNet网络教程_训练自己的图像分类网络resnet101 pytorch-CSDN博客 项目地址&#xff1a;GitHub - Fafa-DL/Awesome-Backbones: Integrate deep learning models for image classification | Backbone learning/comparison…

Java医院绩效考核系统源码:考核目标、考核指标、考核方法、考核结果与奖惩措施

Java医院绩效考核系统源码&#xff1a;考核目标、考核指标、考核方法、考核结果与奖惩措施 随着我国医疗体制的改革广大人民群的看病难&#xff0c;看病贵的问题一直没有得到有效地解决医疗费用的上涨&#xff0c;远远大于大多数家庭收入的增长速度。医院的改革已经势在必行&am…

左右旋分辨

从端头看&#xff0c;切削路径顺时针是右旋&#xff0c;反时针左旋。

OpenCL在移动端GPU计算中的应用与实践

一、引言 移动端芯片性能的不断提升为在手机上进行计算密集型任务&#xff0c;如计算机图形学和深度学习模型推理&#xff0c;提供了可能。在Android设备上&#xff0c;GPU&#xff0c;尤其是高通Adreno和华为Mali&#xff0c;因其卓越的浮点运算能力&#xff0c;成为了异构计…

计算机SCI期刊,中科院3区,易录用,收稿广泛

一、期刊名称 The Journal of Supercomputing 二、期刊简介概况 期刊类型&#xff1a;SCI 学科领域&#xff1a;计算机科学 影响因子&#xff1a;3.3 中科院分区&#xff1a;3区 三、期刊征稿范围 《超级计算杂志》发表有关超级计算各个方面的技术、架构和系统、算法、语…

【PromptCC】遥感图像变化字幕的解耦范式

摘要 以往的方法忽略了任务的显著特异性&#xff1a;对于不变和变化的图像对&#xff0c;RSICC难度是不同的&#xff0c;以一种耦合的方式处理未变化和变化的图像对&#xff0c;这通常会导致变化字幕的混淆。论文链接&#xff1a;https://ieeexplore.ieee.org/stamp/stamp.jsp…

CircuitBreaker断路器-Resilience4j

目录 背景分布式架构面临的问题&#xff1a;服务雪崩如何解决&#xff1f; CircuitBreakerResilience4jCircuitBreaker 服务熔断服务降级三种状态转换例子参数配置案例demo作业 BulkHead隔离特性SemaphoreBulkhead使用了信号量FixedThreadPoolBulkhead使用了有界队列和固定大小…

非root用户crontab定时任务不执行

前言 有一个sh脚本&#xff0c;通过crontab -l写入后&#xff0c;发现并没有执行&#xff0c;手动执行脚本却正常&#xff0c;怀疑是权限上的问题。 排查 在/var/log/cron查看日志发现有" FAILED to authorize user with PAM (Module is unknown)"的报错 解决 …