时间和空间复杂程度计算规则

news2024/11/25 4:56:06

时间复杂度和空间复杂度的计算是算法分析的重要部分。以下是详细的计算方法、示例,以及需要注意的要点。


1. 时间复杂度

时间复杂度描述算法执行所需时间随输入规模增长的增长关系,通常用 O O O 表示法 来表示,关注输入规模 n n n 的增长率。


1.1 时间复杂度的计算方法

  1. 找到最内层操作

    • 确定算法中执行次数最多的基本操作(如赋值、比较、加法等)。
  2. 统计执行次数

    • 从外到内,计算循环、递归或逻辑分支中基本操作的执行次数。
  3. 保留最高阶

    • 只保留执行次数随输入规模 n n n 增长最快的部分,忽略低次项和常数系数。

1.2 常见时间复杂度

  1. 常数时间: O ( 1 ) O(1) O(1)

    • 不依赖于输入规模,执行次数恒定。
    int a = 10;
    a = a + 1; // 常数时间
    
  2. 线性时间: O ( n ) O(n) O(n)

    • 基本操作执行次数与输入规模 n n n成正比。
    for (int i = 0; i < n; i++) {
        printf("%d\n", i); // 执行 n 次
    }
    
  3. 平方时间: O ( n 2 ) O(n^2) O(n2)

    • 嵌套循环中,每个循环迭代 n n n次,基本操作执行 n 2 n^2 n2次。
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            printf("%d, %d\n", i, j); // 执行 n * n 次
        }
    }
    
  4. 对数时间: O ( log ⁡ n ) O(\log n) O(logn)

    • 规模每次减小一半,通常出现在二分查找等算法中。
    while (low <= high) {
        mid = (low + high) / 2;
        if (arr[mid] == target)
            return mid;
        else if (arr[mid] < target)
            low = mid + 1;
        else
            high = mid - 1;
    }
    
  5. 线性对数时间: O ( n log ⁡ n ) O(n \log n) O(nlogn)

    • 通常出现在分治算法(如归并排序)。
    void mergeSort(int arr[], int n) {
        if (n <= 1) return;
        int mid = n / 2;
        mergeSort(left, mid);
        mergeSort(right, n - mid);
        merge(left, right, arr); // 合并操作执行 O(n)
    }
    
  6. 指数时间: O ( 2 n ) O(2^n) O(2n)

    • 通常出现在递归枚举(如穷举法)。
    void subset(int[] arr, int n) {
        if (n == 0) return;
        subset(arr, n - 1);
        subset(arr + [arr[n]], n - 1); // 分成两种选择
    }
    

1.3 示例:时间复杂度的具体分析

示例 1:
for (int i = 0; i < n; i++) {
    printf("%d\n", i);
}
  • 基本操作:printf
  • 执行次数: n n n
  • 时间复杂度: O ( n ) O(n) O(n)
示例 2:
for (int i = 0; i < n; i++) {
    for (int j = 0; j < n; j++) {
        printf("%d, %d\n", i, j);
    }
}
  • 基本操作:printf
  • 执行次数:外层循环执行 n n n次,内层循环每次执行 n n n次,总共 n × n = n 2 n \times n = n^2 n×n=n2 次。
  • 时间复杂度: O ( n 2 ) O(n^2) O(n2)
示例 3:
int i = 1;
while (i <= n) {
    i *= 2;
}
  • 基本操作:i *= 2
  • 执行次数:每次迭代 i i i乘 2,最多执行 l o g 2 n log_2 n log2n 次。
  • 时间复杂度: O ( log ⁡ n ) O(\log n) O(logn)

2. 空间复杂度

空间复杂度描述算法运行时使用的额外内存随输入规模增长的关系,也用 大 O 表示法 表示。


2.1 空间复杂度的计算方法

  1. 统计额外变量

    • 计算算法使用的变量、数组、递归栈的大小。
  2. 输入空间不计入

    • 输入数组或数据结构的存储空间不属于额外空间。
  3. 递归调用的栈空间

    • 如果算法有递归,递归栈的深度乘以每层所需空间。

2.2 常见空间复杂度

  1. 常数空间: O ( 1 ) O(1) O(1)

    • 使用固定数量的变量,无论输入规模如何。
    int a = 0;
    a++;
    
  2. 线性空间: O ( n ) O(n) O(n)

    • 使用额外的数组或数据结构,大小与输入规模 n n n成正比。
    int* temp = (int*)malloc(n * sizeof(int));
    
  3. 递归栈空间: O ( n ) O(n) O(n)

    • 深度为 n n n的递归会使用 O ( n ) O(n) O(n) 的栈空间。
    void recursive(int n) {
        if (n == 0) return;
        recursive(n - 1);
    }
    

2.3 示例:空间复杂度的具体分析

示例 1:
int sum = 0;
for (int i = 0; i < n; i++) {
    sum += i;
}
  • 使用的额外变量:sumi,总共占用固定空间。
  • 空间复杂度: O ( 1 ) O(1) O(1)
示例 2:
int* temp = (int*)malloc(n * sizeof(int));
for (int i = 0; i < n; i++) {
    temp[i] = i;
}
  • 使用的额外空间:长度为 n n n的数组 temp
  • 空间复杂度: O ( n ) O(n) O(n)
示例 3:
void recursive(int n) {
    if (n == 0) return;
    recursive(n - 1);
}
  • 每次递归调用都会占用一个栈帧。
  • 如果递归深度为 n n n,栈空间总大小为 O ( n ) O(n) O(n)

3. 时间复杂度和空间复杂度的对比

算法类型时间复杂度空间复杂度
直接循环 O ( n ) O(n) O(n) O ( 1 ) O(1) O(1)
嵌套循环 O ( n 2 ) O(n^2) O(n2) O ( 1 ) O(1) O(1)
递归算法 O ( 2 n ) O(2^n) O(2n) O ( n ) O(n) O(n)
分治算法 O ( n log ⁡ n ) O(n \log n) O(nlogn) O ( n ) O(n) O(n)
动态规划 O ( n 2 ) O(n^2) O(n2) O ( n 2 ) O(n^2) O(n2)

总结

  • 时间复杂度
    • 根据基本操作的执行次数,分析循环、分支、递归的增长趋势。
  • 空间复杂度
    • 根据额外变量、数组、递归栈的大小,估算内存使用的增长关系。

理解和计算复杂度需要结合实际代码逐行分析,尤其要关注循环和递归结构的执行规律。

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

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

相关文章

使用EFK收集k8s日志

首先我们使用EFK收集Kubernetes集群中的日志&#xff0c;本次实验讲解的是在Kubernetes集群中启动一个Elasticsearch集群&#xff0c;如果企业内已经有了Elasticsearch集群&#xff0c;可以直接将日志输出至已有的Elasticsearch集群。 文章目录 部署elasticsearch创建Kibana创建…

Rust 力扣 - 2266. 统计打字方案数

文章目录 题目描述题解思路题解代码题目链接 题目描述 题解思路 这题可以先求按了多少次相同连续的按钮&#xff0c;所有的连续相同按钮表示的方案数的乘积就是本题答案 我们的关键问题就转换成了按n个连续相同按钮表示的方案数 设f(i)表示按i个连续相同按钮表示的方案数 如…

[Redis#0] iredis: linux上redis超好用的环境配置

目录 Features 特征 Install 安装 Pip Brew Linux的 Download Binary 下载 Binary Usage 用法 Using DSN 使用 DSN Change The Default Prompt更改默认提示 Configuration 配置 Keys Development 发展 Release Strategy 发布策略 Setup Environment 设置环境 De…

flutter 专题十七 Flutter Flar动画实战

Flutter Flar动画实战 在Flare动面出现之前&#xff0c;Flare动画大体可以分为使用AnimationController控制的基础动画以及使用Hero的转场动画&#xff0c;如果遇到一些复杂的场景&#xff0c;使用这些动画方案实现起来还是有难度的。不过&#xff0c;随着Flutter开始支持Flar…

Wekan看板安装部署与使用介绍

Wekan看板安装部署与使用介绍 1. Wekan简介 ​ Wekan 是一个开源的看板式项目管理工具&#xff0c;它的配置相对简单&#xff0c;因为大多数功能都是开箱即用的。它允许用户以卡片的形式组织和跟踪任务&#xff0c;非常适合敏捷开发和日常任务管理。Wekan 的核心功能包括看板…

使用ENSP实现静态路由

一、双路由器静态路由 1.项目拓扑 2.项目实现 (1)路由器AR1配置 进入系统试图 sys将路由器命名为R1 sysname R1进入g0/0/0接口 int g0/0/0将g0/0/0接口IP地址配置为1.1.1.1/24 ip address 1.1.1.1 24进入g0/0/1接口 int g0/0/1将g0/0/1接口IP地址配置为192.168.1.1/24 ip ad…

3、集线器、交换机、路由器、ip的关系。

集线器、交换机、路由器三者的关系 1、集线器2、交换机&#xff08;每个交换机是不同的广播域&#xff0c;ip地址起到划分广播域的作用&#xff09;3、 路由器4、ip地址 1、集线器 一开始两台电脑通信就需要网线就可以&#xff0c;但是三台或者更多主机通信时&#xff0c;就需…

[Unity Demo]从零开始制作空洞骑士Hollow Knight第二十二集:制作游戏的对话系统

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、制作游戏的对话系统 1.通过转移点的门讲解制作对话系统2.以游戏的石碑为例制作确认能力界面总结 前言 hello大家好久没见&#xff0c;之所以隔了这么久…

ChatGPT 桌面版发布了,如何安装?

本章教程教大家如何进行安装。 一、下载安装包 官网地址地址&#xff1a;https://openai.com/chatgpt/desktop/ 支持Windows和MacOS操作系统 二、安装步骤 Windows用户下载之后&#xff0c;会有一个exe安装包&#xff0c;点击运行安装即可。 注意事项&#xff0c;如果Windows操…

Excel求和如何过滤错误值

一、问题的提出 平时&#xff0c;我们在使用Excel时&#xff0c;最常用的功能就是求和了&#xff0c;一说到求和你可能想到用sum函数&#xff0c;但是如果sum的求和区域有#value #Div等错误值怎么办&#xff1f;如下图&#xff0c;记算C列中工资的总和。 直接用肯定会报错&…

librdns一个开源DNS解析库

原文地址&#xff1a;librdns一个开源DNS解析库 – 无敌牛 欢迎参观我的个人博客&#xff1a;无敌牛 – 技术/著作/典籍/分享等 介绍 librdns是一个开源的异步多功能插件式的解析器&#xff0c;用于DNS解析。 源代码地址&#xff1a;GitHub - vstakhov/librdns: Asynchrono…

成都睿明智科技有限公司怎么样可靠不?

在这个日新月异的数字时代&#xff0c;电商行业如同一股不可阻挡的洪流&#xff0c;席卷着每一个消费者的生活。而抖音&#xff0c;作为短视频与电商完美融合的典范&#xff0c;更是为无数商家开辟了一片全新的蓝海。在这片充满机遇与挑战的海洋中&#xff0c;成都睿明智科技有…

栈的应用,力扣394.字符串解码力扣946.验证栈序列力扣429.N叉树的层序遍历力扣103.二叉树的锯齿形层序遍历

目录 力扣394.字符串解码 力扣946.验证栈序列 力扣429.N叉树的层序遍历 力扣103.二叉树的锯齿形层序遍历 力扣394.字符串解码 看见括号&#xff0c;由内而外&#xff0c;转向用栈解决。使用两个栈处理&#xff0c;一个用String,一个用Integer 遇到数字:提取数字放入到数字栈…

Vue3移动端-点餐项目

目录 一、项目构建 1、使用了vite构建vue3项目&#xff0c;其中支持如下图 2、其余路由配置、axios封装、组件封装 都与 后台管理系统 方式一致 二、Vant组件引入 1、安装 &#xff08;vue3使用vant4&#xff09;Vant官方文档 2、全局引入main.ts/js 3、如果是基于 Vite 的…

分词器的概念(通俗易懂版)

什么是分词器&#xff1f;分词器&#xff08;Tokenizer&#xff09;是自然语言处理&#xff08;NLP&#xff09;中的一个关键组件&#xff0c;它的主要功能是将文本数据分解成更小的单元&#xff0c;这些单元可以是单词、子词&#xff08;subword&#xff09;、字符或其他有意义…

【JavaEE进阶】 JavaScript

本节⽬标 了解什么是JavaScript, 学习JavaScript的常⻅操作, 以及使⽤JQuery完成简单的⻚⾯元素操作. 一. 初识 JavaScript 1.JavaScript 是什么 JavaScript (简称 JS), 是⼀个脚本语⾔, 解释型或即时编译型的编程语⾔. 虽然它是作为开发Web⻚⾯的脚本语⾔⽽出名&#xff0c;…

浮点数的表示—IEEE754标准

浮点数的表示—IEEE754标准 引言 我们知道&#xff0c;在计算机中&#xff0c;数字以0和1组成的二进制序列来表示。但是&#xff0c;对于非常大的数字以及非常接近0的数字&#xff0c;简单的存储方式往往会造成精度的丢失。 为了解决这个问题&#xff0c;提供更高效的浮点数…

uniapp vue2项目迁移vue3项目

uniapp vue2项目迁移vue3项目&#xff0c;必须适配的部分 一、main.js 创建应用实例 // 之前 - Vue 2 import Vue from vue import App from ./App Vue.config.productionTip false // vue3 不再需要 App.mpType app // vue3 不再需要 const app new Vue({ ...App }) …

计算机网络(14)ip地址超详解

先看图&#xff1a; 注意看第三列蓝色标注的点不会改变&#xff0c;A类地址第一个比特只会是0&#xff0c;B类是10&#xff0c;C类是110&#xff0c;D类是1110&#xff0c;E类是1111. IPv4地址根据其用途和网络规模的不同&#xff0c;分为五个主要类别&#xff08;A、B、C、D、…

Unity DOTS中的Entity

Unity DOTS中的Entity 在DOTS中entity往往只被看作一个ID&#xff0c;用来查找component&#xff0c;但实际上Unity为了有效地管理entity&#xff0c;在背后还做了一些其他的工作。首先是Entity类本身的定义&#xff0c;它的确跟一个ID差不多&#xff0c;只包含了两个int类型的…