了解时间复杂度和空间复杂度

ops/2024/9/23 0:04:10/

在学习数据结构前,我们需要了解时间复杂度和空间复杂度的概念,这能够帮助我们了解数据结构

算法效率分为时间效率和空间效率

时间复杂度

一个算法的复杂度与其执行的次数成正比。算法中执行基础操作的次数,为算法的时间复杂度。

我们采用大O的渐进表示法。

推导大O阶方法:
1用常数1取代运行时间中的所有加法常数
2在修改后的运行次数函数中,保留最高阶项。
3如果最高阶项存在且不是1,则去除与这个项目相乘的常数。得到的结果就是大O阶。

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

在实际中一般情况关注的是算法的最坏运行情况

举例:

冒泡排序的时间复杂度

 从这个例子我们知道了,不是一层循环时间复杂度就是N,两层就是N^2要看具体算法实现。

二分法时间复杂度分析:

 阶乘递归的时间复杂度

 空间复杂度

对临时储存空间占用大小的量度。计算的是变量的个数。

首先来看冒泡排序的时间复杂度

循环走了N次,重复利用的是一个空间。

斐波那契数列的空间复杂度:

 阶乘的时间复杂度:

算法题

消失的数字

面试题 17.04. 消失的数字 - 力扣(LeetCode)


 

思路1:

排序,如果后一个数字不等于前一个数字加1,那么前一个数字加1,就是要寻找的消失的数字。

这种方法的时间复杂度是N*lgN

思路2:

把0到N加起来,再减去各个数字,得到的数字就是消失的数字。这里的时间复杂度是O(N)。如果先累加,时间复杂度是0(N),依次遍历一遍为O(N)。

int missingNumber(int* nums, int numsSize){int N=numsSize;int ret=(0+N)*(N+1)/2;for(int i=0;i<numsSize;++i){ret-=nums[i];}return ret;}

思路3:

把数组中的所有数字跟0到N异或,剩下的数字就是消失的数字。(我们知道,x^x=0,0^x=x)

int missingNumber(int* nums, int numsSize){int N=numsSize;int x=0;for(int i=0;i<numsSize;i++){x^=nums[i];//x将包含数组nums中所有元素的异或结果}for(int j=0;j<=N;j++){x^=j;}return x;}

189. 轮转数组 - 力扣(LeetCode)

思路1:旋转k次

void rotate(int* nums, int numsSize, int k) {//首先把最后一个数储存起来for(int i=0;i<k;i++){int tmp=nums[numsSize-1];for(int i=numsSize-2;i>=0;i--){nums[i+1]=nums[i];}nums[0]=tmp;}
}

思路2:三段逆置

前k个逆置

后k个逆置

再整体逆置

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;}Reverse(nums,numsSize-k,numsSize-1);Reverse(nums,0,numsSize-k-1);Reverse(nums,0,numsSize-1);
}

思路3:

以空间换时间

 

void _rotate(int*nums,int numsSize,int k,int*tmp)
{k%=numsSize;int n=numsSize;memcpy(tmp,nums+n-k,sizeof(int)*k);//将数组最后 k 个元素复制到 tmp 数组的前 k 个位置memcpy(tmp+k,nums,sizeof(int)*(n-k));//将数组的前 (n-k) 个元素复制到 tmp 数组的剩余位置  memcpy(nums,tmp,sizeof(int)*(n));// // 将 tmp 数组的内容复制回 nums 数组 
}
void rotate(int* nums, int numsSize, int k) 
{int tmp[numsSize];_rotate(nums,numsSize,k,tmp);
}


http://www.ppmy.cn/ops/18064.html

相关文章

Open CASCADE学习|一个点的坐标变换

gp_Trsf 类是 Open CASCADE Technology (OCCT) 软件库中的一个核心类&#xff0c;用于表示和操作三维空间中的变换。以下是该类的一些关键成员和方法的介绍&#xff1a; 成员变量&#xff1a; scale: Standard_Real 类型&#xff0c;表示变换的缩放因子。 shape: gp_TrsfFor…

LRU缓存(哈希+双链表)

题目描述 请你设计并实现一个满足 LRU (最近最少使用) 缓存 约束的数据结构。 实现 LRUCache 类&#xff1a; LRUCache(int capacity) 以 正整数 作为容量 capacity 初始化 LRU 缓存int get(int key) 如果关键字 key 存在于缓存中&#xff0c;则返回关键字的值&#xff0c;…

SpanBert学习

SpanBERT: Improving Pre-training by Representing and Predicting Spans 核心点 提出了更好的 Span Mask 方案&#xff0c;也再次展示了随机遮盖连续一段字要比随机遮盖掉分散字好&#xff1b;通过加入 Span Boundary Objective (SBO) 训练目标&#xff0c;增强了 BERT 的性…

一键设置个性手机壁纸:苹果手机怎么设置动态壁纸?

在苹果手机上设置动态壁纸是一种让你的手机屏幕更生动、更有趣的方式。无论是流动的水滴、绚丽的光影还是动态的星空&#xff0c;动态壁纸可以为你的手机带来全新的视觉体验。苹果手机怎么设置动态壁纸&#xff1f;在本文中&#xff0c;我们将介绍苹果手机上如何设置动态壁纸的…

知识图谱:知识的表示方法

知识表示指的是存储在知识图谱中的数据使用何种语言或者何种数据结构进行描述&#xff0c;从而能够使得知识图谱中的知识运算更加快捷高效。知识表示的方式主要可分为三种&#xff0c;一种是以三元组的形式对知识进行表示&#xff0c;一种是以图结构的形式对知识进行表示&#…

streampetr原版网络nuscenes数据pkl文件中的各字段含义

streampetr原版网络nuscenes数据pkl文件中的各字段含义 每帧数据都包含下列的信息 "token": 该帧数据的标识&#xff0c;具有唯一性 "prev": 该帧数据上一帧数据的token&#xff0c;如果没有就为"" "next": 该帧数据下一帧数据的toke…

通过前端js获取指定年周的开始时间与结束时间(以周一为开始时间)

入参格式&#xff1a;年-周 //截取&#xff1a;具体看入参格式 let year2024; let week2; let weekStartDatenew Date(); let weekEndDatenew Date(); // 创建一个Date对象&#xff0c;设置为指定年份的第一周的周日 let date new Date(year, 0, 1); // 年份, 月份(0…

又重新搭了个个人博客

哈喽大家好&#xff0c;我是咸鱼。 前段时间看到一个学弟写了篇用 Hexo 搭建博客的教程&#xff0c;心中沉寂已久的激情重新被点燃起来。&#xff08;以前搞过一个个人网站&#xff0c;但是因为种种原因最后不了了之&#xff09; 于是花了一天时间参考教程搭了个博客网站&…