#01算法的复杂性

时间复杂度

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;elsereturn 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;elsereturn 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.mzph.cn/news/856056.shtml

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

相关文章

Apple - Authorization Services Programming Guide

本文翻译整理自&#xff1a;Authorization Services Programming Guide&#xff08;更新日期&#xff1a;2011-10-19 https://developer.apple.com/library/archive/documentation/Security/Conceptual/authorization_concepts/01introduction/introduction.html#//apple_ref/d…

JavaScript基础部分知识点总结(Part3)

函数的概念 1. 函数的概念 在JS 里面&#xff0c;可能会定义非常多的相同代码或者功能相似的代码&#xff0c;这些代码可能需要大量重复使用。虽然for循环语句也能实现一些简单的重复操作&#xff0c;但是比较具有局限性&#xff0c;此时我们就可以使用JS 中的函数。函数&…

Tensorflow入门实战 T05-运动鞋识别

目录 一、完整代码 二、训练过程 &#xff08;1&#xff09;打印2行10列的数据。 &#xff08;2&#xff09;查看数据集中的一张图片 &#xff08;3&#xff09;训练过程&#xff08;训练50个epoch&#xff09; &#xff08;4&#xff09;训练结果的精确度 三、遇到的问…

安装VSCode创建注册表出错,RegCreateKey错误码5

今天对VSCode进行做更新安装&#xff0c;谁知道安装到最后弹出下面这么个错误 找到windows下管用的一种解决办法&#xff1a; winR打开运行&#xff0c;输入 regedit找到错误提示中的路径&#xff0c;HKEY_CURRENT_USER\Software\Classes\VSCode.class\open (图中的错误注册表…

第 三 方 组 件 e l e m e n t - u i[Vue]

一、组件之间的传值 组件可以由内部的Data提供数据&#xff0c;也可以由父组件通过prop的方式传值。 兄弟组件之间可以通过Vuex等统一数据源提供数据共享 第一种 Movie.vue <template><div><h1>我才不要和你做朋友</h1></div></template&…

嵌入式开发十九:SysTick—系统定时器

在前面实验中我们使用到的延时都是通过SysTick进行延时的。 我们知道&#xff0c;延时有两种方式&#xff1a;软件延时&#xff0c;即CPU 循环等待产生的&#xff0c;这个延时是不精确的。第二种就是滴答定时器延时&#xff0c;本篇博客就来介绍 STM32F4 内部 SysTick 系统定时…

高德地图轨迹回放/轨迹播放

前言 本篇文章主要介绍高德地图的轨迹回放或播放的实现过程&#xff0c;是基于vue2实现的功能&#xff0c;同时做一些改动也是能够适配vue3的。其中播放条是用的是element UI中的el-slider组件&#xff0c;包括使用到的图标也是element UI自带的。可以实现轨迹的播放、暂停、停…

【windows|004】BIOS 介绍及不同品牌电脑和服务器进入BIOS设置的方法

&#x1f341;博主简介&#xff1a; &#x1f3c5;云计算领域优质创作者 &#x1f3c5;2022年CSDN新星计划python赛道第一名 &#x1f3c5;2022年CSDN原力计划优质作者 ​ &#x1f3c5;阿里云ACE认证高级工程师 ​ &#x1f3c5;阿里云开发者社区专家博主 &#x1f48a;交流社…

【ARM】如何通过Keil MDK查看芯片的硬件信息

【更多软件使用问题请点击亿道电子官方网站】 1、文档目标&#xff1a; 解决在开发过程中对于开发项目所使用的的芯片的参数查看的问题 2、问题场景&#xff1a; 在项目开发过程中&#xff0c;经常需要对于芯片的时钟、寄存器或者一些硬件参数需要进行确认。大多数情况下是需…

wps-文档-js宏-批量修改表格格式

目录 前言开启JS宏我的脚本参考API文档 前言 由于需要修改word的表格的格式&#xff0c;一个一个的修改太慢了&#xff0c;所以需要通过宏的方式来修改&#xff0c;需要注意的是低版本可能没有JS宏… 开启JS宏 切换到工具–>点击开发工具 点击之后功能栏会变化成这样 选…

Dell戴尔灵越Inspiron 16 Plus 7640/7630笔记本电脑原装Windows11下载,恢复出厂开箱状态预装OEM系统

灵越16P-7630系统包: 链接&#xff1a;https://pan.baidu.com/s/1Rve5_PF1VO8kAKnAQwP22g?pwdjyqq 提取码&#xff1a;jyqq 灵越16P-7640系统包: 链接&#xff1a;https://pan.baidu.com/s/1B8LeIEKM8IF1xbpMVjy3qg?pwdy9qj 提取码&#xff1a;y9qj 戴尔原装WIN11系…

CFD笔记

CFD 定常流动与非定常流动 定常流动&#xff1a;流体流动过程中各物理量均与时间无关; 非定常流动&#xff1a;流体流动过程中某个或某些物理量与时间有关. 运动黏度 运动粘度定义&#xff1a; v μ ρ v \frac{\mu}{\rho} vρμ​&#xff0c;其中 μ \mu μ​表示粘度…

Node.js进阶——数据库

文章目录 一、步骤1、安装操作 MySQL数据库的第三方模块(mysql)2、通过 mysql 模块连接到 MySQL 数据库3、测试 二、操作 mysql 数据库1、查询语句2、插入语句3、插入语句快捷方式4、更新数据5、更新语句快捷方式6、删除数据7、标记删除 二、前后端的身份认证1、web开发模式1&a…

如何用python调用C++处理图片

一. 背景 用pyhton可直接调用C&#xff0c;减少重写的工作量&#xff1b;部分逻辑运算&#xff0c;C的执行效率高&#xff0c;可进行加速。 下面就一个简单的C滤镜&#xff08;彩色图转灰度图&#xff09;为例&#xff0c;展示python调用C 二. 代码实现 代码结构如下&#x…

如何解决跨区域文件传输存在的安全管控问题?

⼤型企业和集团为扩⼤市场份额、优化资源配置&#xff0c;会在不同地区设⽴多级下属分⽀机构、研发中心、实验室等&#xff0c;存在研发数据横向或纵向流转的需求&#xff0c;研发数据进行跨区域文件传输的场景。跨区域可能是网络区域&#xff0c;也可能是地理区域&#xff0c;…

2-10 基于matlab的动态时间归整(DTW)算法

基于matlab的动态时间归整&#xff08;DTW&#xff09;算法。16页的试验文档。以一个能识别数字0&#xff5e;9的语音识别系统的实现过程为例&#xff0c;阐述了基于DTW算法的特定人孤立词语音识别的基本原理和关键技术。其中包括对语音端点检测方法、特征参数计算方法和DTW算法…

elasticsearch的安装和配置

单节点安装与部署 我们通过docker进行安装 1.docker的安装 如果以及安装了docker就可以跳过这个步骤。 首先更新yum: yum update安装docker: yum install docker查看docker的版本&#xff1a; docker -v此时我们的docker就安装成功了。 2.创建网络 我们还需要部署kiban…

八大排序————C语言版实现

Hello&#xff0c;各位未来的高级程序员们&#xff0c;大家好&#xff0c;今天我就来为大家讲解一下有关排序的内容&#xff0c;我们常见的排序就是我们接下来要讲的这八个排序&#xff0c;我们平常所说的排序有十大排序&#xff0c;我们这里的八大排序是我们生活中最为常见的八…

idea的右边栏maven不见了(丢了)解决方案以及idea无法识别maven项目

前言 众所周知&#xff0c;idea是java开发中不可缺少的利器&#xff0c;但是由于功能过多&#xff0c;导致奇怪的问题也很多 问题汇总 idea的右边栏maven丢了 idea无法识别maven项目 对应的解决办法 idea的右边栏maven丢了 原因可能是被自己手动移除了 或者 项目没被正确…

CTF入门指南

何为CTF &#xff1f; CTF&#xff08;Capture The Flag&#xff09;夺旗比赛&#xff0c;在网络安全领域中指的是网络安全技术人员之间进行技术竞技的一种比赛形式。CTF起源于1996年DEFCON全球黑客大会&#xff0c;以代替之前黑客们通过互相发起真实攻击进行技术比拼的方式。…