【数据结构】—时间复杂度or空间复杂度以及基础题目练习

news2025/1/18 10:55:05

小菜坤日常上传gitee代码:https://gitee.com/qi-dunyan
❤❤❤
个人简介:双一流非科班的一名小白,期待与各位大佬一起努力!
推荐网站:cplusplus.com
在这里插入图片描述

目录

  • 前言
  • 算法与复杂度
    • 时间复杂度
    • 大O的渐进表示法
    • 时间复杂度计算练习
    • 空间复杂度
  • 题目练习
    • 题目一
    • 题目二

前言

1. 什么是数据结构?
数据结构(Data Structure)是计算机存储、组织数据的方式,指相互之间存在一种或多种特定关系的数据元素的集合。
我们在前面写的通讯录,其实就是一个数据结构
2.什么是算法?
算法(Algorithm):就是定义良好的计算过程,他取一个或一组的值为输入,并产生出一个或一组值作为输出。简单来说算法就是一系列的计算步骤,用来将输入数据转化成输出结果。
这里的概念性的内容看一下就行,后面才是重点

算法与复杂度

衡量一个算法好坏的标准是什么?我相信有一些和我一样的小白,曾天真的认为只要代码写的简洁,这就是一个好代码,就比如之前学过的斐波那契数,很简单的一个递归就可以解决。如下:

long long Fib(int N)
{
 if(N < 3)
      return 1;
 return Fib(N-1) + Fib(N-2);
}

简简单单三行代码,就可以实现,但是我们发现,假如我们输入的数字大一点,我们的计算机就计算不出来了,比如输入一个50,就会出现如下情况:
在这里插入图片描述
但假如我们换另一种方式,便可以很快的打印出来:
在这里插入图片描述
所以,我们不能仅仅简单的以代码的长短来衡量代码的好坏,而衡量一个算法,主要是看它的复杂度。
算法与复杂度
算法在编写成可执行程序后,运行时需要耗费时间资源和空间(内存)资源 。因此衡量一个算法的好坏,一般是从时间和空间两个维度来衡量的,即时间复杂度和空间复杂度
时间复杂度主要衡量一个算法的运行快慢,而空间复杂度主要衡量一个算法运行所需要的额外空间。在计算机发展的早期,计算机的存储容量很小。所以对空间复杂度很是在乎。但是经过计算机行业的迅速发展,计算机的存储容量已经达到了很高的程度。所以我们如今已经不需要再特别关注一个算法的空间复杂度。时间复杂度才是如今的主要关注点

接下来我们便来瞅一瞅时间复杂度以及空间复杂度

时间复杂度

概念
这里官方的定义比较繁多,我们只需要知道,时间复杂度就是算法中的基本操作的执行次数,就比如下面这段代码:

#include<stdio.h>
int main()
{
	int n = 0;
	int count = 0;
	scanf("%d", &n);
	for (int i = 0; i < n; i++)
	{
		for (int j = 0; j < n; j++)
		{
			count++;
		}
	}
	for (int i = 0; i < 2 * n; i++)
	{
		count++;
	}
	for (int i = 0; i < 10; i++)
	{
		count++;
	}
	printf("%d", count);
	return 0;
}

这里count一共执行了n^2+2*n+10次,这就是这个算法的时间复杂度。但实际上,我们其实并不一定要计算精确的执行次数,而只需要大概执行次数,这里就提到了大O的渐进表示法。

大O的渐进表示法

推导大O阶方法:

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

这里我们根据这个推导公式,就可以判断,我们上面的时间复杂度用大O的渐进表示就是O(N^2)

但是对于有些算法,它可能存在最优、平均以及最坏可能,就比如我们在N个数据中,查找我们想要的数字val,它可能存在以下三中可能:
最优:一次就找到
平均:找了N/2次
最坏:最后才找到,即找了N次
那么这里我们取的是最坏情况,所以这里的时间复杂度为O(N)。
为什么会不取最优或者平均呢?“凡事做好最坏的打算”,这里的凡事就包含了这个。

时间复杂度计算练习

题目一:

// 计算Func2的时间复杂度?
void Func2(int N)
{
int count = 0;
for (int k = 0; k < 2 * N ; ++ k)
{
++count;
}
int M = 10;
while (M–)
{
++count;
}
printf(“%d\n”, count);
}
一共运行2*N+10次

时间复杂度:O(N),因为这里的最高阶项为1,然后去掉最高阶项的常数,就是N

题目二:

// 计算Func3的时间复杂度?
void Func3(int N, int M)
{
int count = 0;
for (int k = 0; k < M; ++ k)
{
++count;
}
for (int k = 0; k < N ; ++ k)
{
++count;
}
printf(“%d\n”, count);
}

O(M+N),因为有两个未知数M、N

题目三:

// 计算Func4的时间复杂度?
void Func4(int N)
{
int count = 0;
for (int k = 0; k < 100000000; ++ k)
{
++count;
}
printf(“%d\n”, count);
}

O(1),因为100000000是个常数,常数都用O(1)表示

题目四:冒泡排序的时间复杂度

void bubble_sort(int sz, int *arr)
{
int t = 0;//趟数
for (t = 0; t < sz - 1; t++)
{
int j = 0;
for (j = 0; j < sz - 1 - t; j++)
{
if (arr[j] > arr[j + 1])
{
int tmp = arr[j];
arr[j] = arr[j + 1];
arr[j+1]=tmp;
}
}
}
}

冒泡排序,第一次排序N个,第二次N-1,第三次N-2,第四次N-3…第N次1
加起来刚好是个等差数列求和即(N*(N+1))/2,这里展开后,取最高项,并且去掉常数,就算O(N^2)

题目四:二分查找时间复杂度

int BinarySearch(int* a, int n, int x)
{
assert(a);
int begin = 0;
int end = n-1;
// [begin, end]:begin和end是左闭右闭区间,因此有=号
while (begin <= end)
{
int mid = begin + ((end-begin)>>1);
if (a[mid] < x)
begin = mid+1;
else if (a[mid] > x)
end = mid-1;
else
return mid;
}
return -1;
}

在这里插入图片描述
所以时间复杂度为O(logN) 、有时也会这么写->O(lgN)

空间复杂度

简单来说空间复杂度算的是变量的个数。也使用大O渐进表示法,规则与时间复杂度相同。
注意:函数运行时所需要的栈空间(存储参数、局部变量、一些寄存器信息等)在编译期间已经确定好了,因此空间复杂度主要通过函数在运行时候显式申请的额外空间来确定。
例题:

void BubbleSort(int* a, int n)
{
assert(a);
for (size_t end = n; end > 0; --end)
{
int exchange = 0;
for (size_t i = 1; i < end; ++i)
{
if (a[i-1] > a[i])
{
Swap(&a[i-1], &a[i]);
exchange = 1;
}
}
if (exchange == 0)
break;
}
}

这里的数组a以及n,都是函数参数,是运行这个函数时已经创建好了的,只有变量i、end、还有exchange是我们在运行这个函数的时候才申请空间,所以是常数个,所以空间复杂度O(1)

题目练习

题目一

数组nums包含从0到n的所有整数,但其中缺了一个。请编写代码找出那个缺失的整数。你有办法在O(n)时间内完成吗?
例:输入:[9,6,4,2,3,5,7,0,1]
输出:8

分析:这里我们有三种思路,第一种时是进行求和,求0-n的和(等差数列公式:(n+1)n/2直接算出来),然后遍历数组,进行求和,两者再相减即可。
时间复杂度O(N)√
第二种:
先排序,再遍历,我们知道,冒泡排序的时间复杂度为O(N^2),而qsort时间复杂度是O(N
logN),两者都不符合,所以直接不考虑这种
第三种:
异或法,两两相等的数异或为0,将数组元素异或,再将异或结果与0-n异或,就可找出缺失的数。
时间复杂度O(N)√
思路一实现:

 int missingNumber(int* nums, int numsSize) {
     int n = numsSize;
     //0-n之和
     int sum = n * (n + 1) / 2;
     int i = 0;
     int m = 0;
     //数组元素之和
     for (i = 0; i < n; i++)
     {
         m += nums[i];
     }
     //返回两者之差
     return sum - m;
 }

思路二实现:

 int missingNumber(int* nums, int numsSize) {


     int ret = 0;
     int i = 0;
     int j = 0;
     //先异或所有元素
     for (i = 0; i < numsSize; i++)
     {
         ret ^= nums[i];
     }
     //再把所有元素异或从0-numsSize,找到单身狗
     for (j = 0; j < numsSize + 1; j++)
     {
         ret ^= j;
     }
     return ret;
 }

题目二

给你一个数组,将数组中的元素向右轮转 k 个位置,其中 k 是非负数。
示例 1:
输入: nums = [1,2,3,4,5,6,7], k = 3
输出: [5,6,7,1,2,3,4]
解释:
向右轮转 1 步: [7,1,2,3,4,5,6]
向右轮转 2 步: [6,7,1,2,3,4,5]
向右轮转 3 步: [5,6,7,1,2,3,4]

思路一:空间换时间,开辟一个新数组,先拷贝后面的k个元素,再拷贝前面的元素,再把整个数组的元素拷贝到原数组。
时间复杂度O(N)、空间复杂度O(N)
实现:

void rotate(int* nums, int numsSize, int k){

    k%= numsSize;
    int arr[numsSize];
    //先拷贝后面k个元素
    int j=0;
    for(int i=numsSize-k; i<numsSize; i++)
    {
        arr[j]=nums[i];
        ++j;
    }
    //再拷贝前面的元素
    for(int i=0; i<numsSize-k; ++i)
    {
        arr[j]=nums[i];
        ++j;
    }
    //整体拷贝
    for(int i=0; i<numsSize; ++i)
    {
        nums[i]=arr[i];
    }
}

思路二:三次反转法、 时间复杂度:O(n),空间O(1)
先反转k前面的数组元素,再反转后面k个元素,最后再整体反转
例:1 2 3 4 5 k=2
第一次:3 2 1 4 5
第二次:3 2 1 5 4
第三次:4 5 1 2 3
实现:

void rotate(int* nums, int numsSize, int k) {
    //三次反转
    k %= numsSize;
    int* right1 = nums + numsSize - 1;
    int* left1 = right1 - k + 1;
    int* right = left1 - 1;
    int* left = nums;
    int tmp = 0;
    while (left1 < right1)
    {
        tmp = *right1;
        *right1 = *left1;
        *left1 = tmp;
        left1++;
        right1--;
    }
    while (left < right)
    {
        tmp = *left;
        *left = *right;
        *right = tmp;
        left++;
        right--;
    }
    left = nums;
    right1 = nums + numsSize - 1;
    while (left < right1)
    {
        tmp = *left;
        *left = *right1;
        *right1 = tmp;
        left++;
        right1--;
    }
}

思路三:一个一个旋转,旋转k次 时间复杂度O(N^2),空间O(1)

 void rotate(int* nums, int numsSize, int k) {
int* right = nums + numsSize - 1;
int i = 0;
k %= numsSize;
while (k--)
{
    int tmp = *right;
    for (i = 1; i < numsSize; i++)
    {
        *(nums + numsSize - i) = *(nums + numsSize - 1 - i);
    }
    *nums = tmp;
}
}

(思路三最后未通过测试)


生活原本沉闷,但跑起来就会有风!

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

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

相关文章

[附源码]java毕业设计社区疫情防控管理系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

MySQL纯代码复习(上)

前言 本文章是用于总结尚硅谷MySQL教学视频的记录文章&#xff0c;主要用于复习&#xff0c;非商用 原视频连接&#xff1a;https://www.bilibili.com/video/BV1iq4y1u7vj/?p21&spm_id_frompageDriver&vd_sourcec4ecde834521bad789baa9ee29af1f6c https://www.bilib…

【设计模式】 - 创建者模式 -建造者模式

1. 建造者模式 1.1 概述 将一个复杂对象的构建与表示分离&#xff0c;使得同样的构建过程可以创建不同的表示。 分离了部件的构造(由Builder来负责)和装配(由Director负责)。 从而可以构造出复杂的对象。这个模式适用于&#xff1a;某个对象的构建过程复杂的情况。 由于实现了…

小目标检测:基于切图检测的yolov5小目标检测

目前在目标检测方面有着众多的检测框架,比如两阶段的FasterRcnn、以及yolo系列的众多模型。yolo系列在实际中用的最多,一方面性能确实不错,另一方面具有着较多的改进型系列。今天我们主要使用的yolov5系列。具体原理过程就不多说了,大家自行百度。放一张v5的网络结构图。 大…

计算机网络部分(一)

1 请描述 TCP/IP 协议中主机与主机之间通信的三要素 答&#xff1a; IP 地址&#xff08;IP address&#xff09; 子网掩码&#xff08;subnet mask&#xff09; IP 路由&#xff08;IP router&#xff09; 扩展&#xff1a; TCP/IP定义&#xff1a;TCP/IP是基于TCP和IP这两个…

883. 三维形体投影面积

883. 三维形体投影面积 在 n x n 的网格 grid 中&#xff0c;我们放置了一些与 x&#xff0c;y&#xff0c;z 三轴对齐的 1 x 1 x 1 立方体。 每个值 v grid[i][j] 表示 v 个正方体叠放在单元格 (i, j) 上。 现在&#xff0c;我们查看这些立方体在 xy 、yz 和 zx 平面上的投…

【Java八股文总结】之Java设计模式

文章目录Java设计模式一、设计模式概述1、什么是设计模式&#xff1f;2、设计模式的6大原则3、具体的设计模式1、单例模式Q&#xff1a;为什么使用两个 if (singleton null) 进行判断&#xff1f;Q&#xff1a;volatile 关键字的作用&#xff1f;2、原型模式补充&#xff1a;浅…

yml中无法解析类 ‘HikariDataSource‘

目录 yml中无法解析类 HikariDataSource ⭐关于HikariDataSource的信息 yml中无法解析类 HikariDataSource 修改之前该行是报红的 具体代码 # 配置项目信息 spring:profiles:active: prod # yml中配置文件的环境配置&#xff0c;dev&#xff1a;开发环境&#xff0c;t…

06_通信过程

知识点1【通信过程概述】 2、PC和集线器Hub 2、PC机和交换机switch 2、路由器&#xff08;重要哟&#xff09; 知识点1【通信过程概述】 1、PacketTracer5.exe 安装 一路next 2、PC和集线器Hub 选择集线器 选择主机&#xff1a; 选择线 一个集线器4台主机&#xff1a; 配…

ZooKeeper教程

官网&#xff1a;Apache ZooKeeper 什么是Zookeeper&#xff1f; ZooKeeper是一个集中服务&#xff0c;用于维护配置信息、命名、提供分布式同步和组服务。所有这些类型的服务都以某种形式被分布式应用程序使用。每次实施它们时&#xff0c;都要进行大量的工作来修复不可避免的…

Flink水位线-详细说明

文章目录时间语义Flink 中的时间语义?哪种时间语义更重要?1. 水位线&#xff08;Watermark&#xff09;1.1 什么是水位线?1.2 如何生成水位线?1.3 水位线的传递1.4 水位线的计算&#x1f48e;&#x1f48e;&#x1f48e;&#x1f48e;&#x1f48e; 更多资源链接&#xff0…

C#编程流程控制与集合类型

目录 选择语句 if-else语句 switch语句 集合一览 数组 列表 字典 迭代 for循环 foreach循环 while循环 超越无限 总结 本文主要来自<<C#实践入门>>哈里森.费隆 著&#xff0c;仅用为做笔记。 本章将专注以下主题: 选择语句。使用数组(Array)、字典(…

高级UI——Path测量

前言 在Path在UI体系当中不论是在自定义View还是动画&#xff0c;都占有举足轻重的地位。绘制Path&#xff0c;可以通过Android提供的API&#xff0c;或者是贝塞尔曲线、数学函数、图形组合等等方式&#xff0c;而要获取Path上每一个构成点的坐标&#xff0c;一般需要知道Path…

力扣刷题记录120.1-----718. 最长重复子数组

目录一、题目二、代码三、运行结果一、题目 二、代码 class Solution { public://dp[i][j]表示以 i j为末尾 最长公共子序列int findLength(vector<int>& nums1, vector<int>& nums2) {int i,j;int return_int0;vector<vector<int>> dp(n…

数据可视化模块 Matplotlib详解

本文主要介绍python 数据可视化模块 Matplotlib&#xff0c;并试图对其进行一个详尽的介绍。 通过阅读本文&#xff0c;你可以&#xff1a; 了解什么是 Matplotlib掌握如何用 Matplotlib 绘制各种图形&#xff08;柱状图、饼状图、直方图等&#xff09;掌握如何定制图形的颜色和…

WiFi连接满格信号但是不能上网?

WiFi已经成为人们日常生活中离不开的东西了&#xff0c;不论是手机还是笔记本电脑。但是有时候会遇到WiFi连接满格信号但是无法上网的情况&#xff0c;这是怎么回事呢&#xff1f;下面就和小编一起来看看吧。 WiFi满信号但是无法上网可能是这几个原因&#xff1a; 1、路由器网络…

使用 Docker 快速搭建 Rust 的 Jupyter Notebook

在 Jupyter notebook 上面运行 Python 程序非常&#xff0c;实际上 Jupyter 也支持其他的内核。 我们可以使用 docker 运行一个已经安装好 Rust Conda Jupyter Notebook 的的容器。 如下&#xff1a; docker run --name jupyter-rust -d -p 8899:8899 -v pwd:/opt/noteboo…

JavaScript作用域(作用域概述、变量的作用域、作用域链)、JavaScript预解析(特殊案例)

目录 JavaScript作用域 作用域概述 变量的作用域 作用域链 JavaScript预解析 特殊案例 JavaScript作用域 作用域概述 通常来说&#xff0c;一段程序代码中所用到的名字并不总是有效和可用的&#xff0c;而限定这个名字的可用性的代码范围就是这个名字的作用域。作用域的…

【C语言经典例题】——程序员必须会的经典基础例题(三)

关于C语言的一些基础经典题目放在专栏&#xff1a;[C语言刷题] 小菜坤日常上传gitee代码&#xff1a;https://gitee.com/qi-dunyan ❤❤❤ 个人简介&#xff1a;双一流非科班的一名小白&#xff0c;期待与各位大佬一起努力&#xff01; 推荐网站&#xff1a;cplusplus.com 目录…

LeNet-5学习笔记

LeNet-5 网络结构 输入→卷积&#xff08;C1&#xff09;→池化&#xff08;S2&#xff09;→卷积&#xff08;C3&#xff09;→池化&#xff08;S4&#xff09;→全连接(F5)→全连接&#xff08;F6&#xff09;→输出&#xff08;Output&#xff09; 卷积神经网络的构成 输…