【算法基础(1)】认识时间复杂度和常用排序算法

news2025/1/20 1:51:32

1 认识时间复杂度

1.1 什么是时间复杂度?

时间复杂度是一个函数,它定性描述该算法的运行时间,在软件开发中,时间复杂度就是用来方便开发者估算出程序运行时间,通常用算法的操作单元数量来代表程序消耗的时间,这里默认CPU的每个单元运行消耗的时间都是相同的。假设算法的问题规模为n,那么操作单元数量便用函数f(n)来表示,随着数据规模n的增大,算法执行时间的增长率和f(n)的增长率呈现一定的关系,这称作为算法的渐近时间复杂度,简称时间复杂度,记为 O(f(n)),其中n指的是指令集的数目。

1.2 什么是big O

big O用来表示算法执行时间的上界,也可以理解为最差情况下运行的时间,数据量和顺序等情况对算法的执行时间有非常大的影响,这里假设的是某个输入数据用该算法运行的时间,比其他数据的运算时间都要长。

插入排序的时间复杂度我们都说是O(n^2) ,但是插入排序的时间复杂度和输入数据有很大的关系,假如输入数据是完全有序的,则插入排序的时间复杂度是O(n),假如输入的数据是完全倒序的,则时间复杂度是O(n^2),所以最坏是O(n^2) 的时间复杂度,我们说插入排序的时间复杂度为O(n^2)

快速排序是O(nlogn),快速排序的在最差的情况下时间复杂度是O(n^2) ,一般情况下是O(nlogn)所以严格从big O的定义来讲,快速排序的时间复杂度应该是O(n^2),但是我们依然说快速排序的时间复杂度是O(nlogn),这是业内默认的规定。

二分查找的时间复杂度是O(logn),每次二分数据规模减半,直到数据规模减少为 1,最后相当于求2的多少次方等于n,相当于分割了logn次。

归并排序的时间复杂度是O(nlogn),自顶而下的归并,从数据规模为n分割到1,时间复杂度是O(logn),然后不断向上归并的时间复杂度是O(n),总体时间复杂度是O(nlogn)

树的遍历复杂度一般是O(n)n是树的节点个数,选择排序时间复杂度是O(n^2),我们会在对应的章节逐步分析各个数据结构和算法的复杂度。更多的时间复杂度分析和推导可参阅主定理。

1.3 常见时间复杂度

1.3.1 O(1):常数复杂度
let n = 100;
1.3.2 O(logn):对数复杂度
//二分查找非递归
var search = function (nums, target) {
  let left = 0,
    right = nums.length - 1;
  while (left <= right) {
    let mid = Math.floor((left + right) / 2);
    if (nums[mid] === target) {
      return mid;
    } else if (target < nums[mid]) {
      right = mid - 1;
    } else {
      left = mid + 1;
    }
  }
  return -1;
};
1.3.3 O(n):线性时间复杂度
for (let i = 1; i <= n; i++) {
  console.log(i);
}
1.3.4 O(n^2):平方 (嵌套循环)
for (let i = 1; i <= n; i++) {
  for (let j = 1; j <= n; j++) {
    console.log(i);
  }
}
  
for (let i = 1; i <= n; i++) {
  for (let j = 1; j <= 30; j++) { //嵌套的第二层如果和n无关则不是O(n^2)
    console.log(i);
  }
}
1.3.5 O(2^n):指数复杂度
for (let i = 1; i <= Math.pow(2, n); i++) {
  console.log(i);
}
1.3.6 O(n!):阶乘
for (let i = 1; i <= factorial(n); i++) {
  console.log(i);
}

2 常见排序算法

2.1 选择排序

算法步骤:

首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置。

再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。

重复第二步,直到所有元素均排序完毕。

选择排序是一种简单直观的排序算法,无论什么数据进去都是 O(n²) 的时间复杂度。所以用到它的时候,数据规模越小越好。唯一的好处可能就是不占用额外的内存空间。

function selectSort(arr) {
    for (let i=0;i<arr.length-1;i++) {
        let min = i;
        for (let j=min+1;j<arr.length;j++) {
            if (arr[min] > arr[j]) {
                min = j;
            }
        }
        let temp = arr[i];
        arr[i] = arr[min]
        arr[min] = temp;
    }
    return arr;
}

2.2 冒泡排序

比较相邻的元素。如果第一个比第二个大,就交换它们两个;

第一遍循环0-n 确定n的值 都是找出最大的值冒泡在最上面

第二遍循环0-n-1 确定n-1的值

第三遍循环0-n-2 确定n-2的值

function bubleSort(arr) {
    for (let i = 0;i<arr.length-1;i++) {  // 循环轮次
        for (let j=0;j< arr.length-i-1;j++) { // 每轮比较次数
            if (arr[j] > arr[j+1]) { // 相邻比较
                let temp = arr[j]
                arr[j] = arr[j+1]
                arr[j+1] = temp
            }
        }
    }
    return arr;
}

2.3 插入排序

第一次 前俩个数值排序

第二次循环 前三个数值排序,比较最后一个数值和新的数值,然后插入到指定位置

在这里插入图片描述

在这里插入图片描述

function insertSort(arr) {
    for (let i = 1;i<arr.length;i++) {  // 循环轮次
        let end = i;
        let curr = arr[i]
        while(end > 0 && curr < arr[end-1]) { // 直到第一位 或者 当前的数不是最小值
            arr[end] = arr[end - 1] // 移动比当前值小的值到后一位
            end--
        }
        arr[end] = curr // 插入当前值
    }
    return arr;
}

2.4 异或运算

当且仅当只有一个表达式的某位上为 1 时,结果的该位才为 1。否则结果的该位为 0,简单的说就是-----相同为 0,不同为 1

语法:result = expression1 ^ expression2
按位异或 是对两个表达式执行 按位异或,先将两个数据转化为二进制数,然后进行 按位异或运算,只要位不同结果为 1,否则结果为 0

例如:
let a = 5;
let b = 8;
let c = a ^ b;
console.log(c) // 13

解析:
a 转二进制数为:0101
b 转二进制数为:1000
那么按照 按位异或 运算之后得到:1101(相同为 0,不同为 1),得到 c 的值就是 13
特点

一、满足交换率

a ^ b == b ^ a

二、两个相同的数字异或操作得到的一定是 0

a^a === 0

三、0 和 其他数字异或操作得到的一定是其他数字

0^a === a

2.5 练习题

一、给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素

let arr = [1, 3, 1, 2, 2, 7, 3, 6, 7]

// es5 解决方案
function fnc(arr){
    let result = 0;
    for(let i = 0; i < arr.length; i++){
        result  = result ^ arr[i];
    }
    return result;
}

// es6 解决方案
function fnc(arr){
    return arr.reduce((a, b) => a ^ b, 0);
}

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

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

相关文章

pageoffice在线编辑word文件并禁止选中

一、整篇文档禁止选中 wordDoc.setDisableWindowSelection(true); //禁止word的选择文字功能 二、根据条件判断是否禁止选中 比如&#xff1a;选中内容超过一定字数&#xff0c;取消选中 解决方案&#xff1a;使用后端提供的OnWordSelectionChange事件。 PageOfficeCtrl po…

sgRNAs基因编辑

CRISPR-Cas9知识学习笔记 https://www.163.com/dy/article/FGCP58KC0532AN5N.html https://crispr.dbcls.jp CRISPR&#xff08;clustered regularly interspaced short palindromic repeats&#xff0c;成簇的规律间隔短回文重复序列&#xff09;和CRISPR-associated protein …

Spring Cloud Gateway服务网关的部署与使用(结合nacos)

一、微服务网关1.什么是微服务网关在传统的单体架构中&#xff0c;我们只需要开放一个服务给客户端调用即可。但是微服务架构中是将一个系统拆分成多个微服务&#xff0c;不同的微服务一般会有不同的网络地址&#xff0c;客户端在访问这些微服务时必须记住几十甚至百个地址&…

springboot多项目结构

微服务的目录结构一般分为如下几个模块&#xff1a; 当我们做的项目稍微大一点之后&#xff0c;就会经常遇到需要把不同的模块分离出来的时候&#xff0c;比如微信的朋友圈、微信支付、聊天服务等模块&#xff0c;像这种微服务项目一般都会把base、common、前端抽离出来。 com…

DP8403国产3W双通道无滤波器D类立体声音频放大器兼容替代CS8403

目标DP8403简介功能框图&#xff1a;DP8403主要特性DP8403简介 DP8403是3W双通道无滤波器D类立体声音频功率放大器芯片&#xff0c;能够以D类放大器的效率提供AB类功率放大器的性能。采用D类结构&#xff0c;DP8403 能够在 4Ω负载和 5V 电源条件下&#xff0c;提供高达 3W 输…

MySQL (五)------数据库三范式、外键约束、多表间关系、多表关联查询、子查询

数据库三范式 好的数据库设计对数据的存储性能和后期的程序开发&#xff0c;都会产生重要的影响。建立科学的&#xff0c;规范的数据库就需要满足一些规则来优化数据的设计和存储&#xff0c;这些规则就称为范式。 1.1 第一范式: 确保每列保持原子性 第一范式是最基本的范式…

深入理解java反射原理

系列文章目录 文章目录系列文章目录前言一、 如何获取反射中的Class对象&#xff1f;二、反射的步骤三、详细解答1. 获取对象类的实例2、newInstance() 的实现方式3、获取Method对象4. 调用invoke()方法。总结前言 反射是在运行状态中&#xff0c;对于任意一个类&#xff0c;都…

C 程序设计教程(10)—— 数据输入函数(scanf)用法详解

C 程序设计教程&#xff08;10&#xff09;—— 数据输入函数&#xff08;scanf&#xff09;用法详解 该专栏主要介绍 C 语言的基本语法&#xff0c;作为《程序设计语言》课程的课件与参考资料&#xff0c;用于《程序设计语言》课程的教学&#xff0c;供入门级用户阅读。 目录…

Ubuntu安装PyTango步骤

继续上一篇&#xff1a; https://blog.csdn.net/woshigaowei5146/article/details/128443892?spm1001.2014.3001.5502 环境 虚拟机&#xff1a;VMware Ubuntun&#xff1a;20.04LTS Tango&#xff1a;9.3.5 安装 PyTango作为官方debian/ubuntu包在linux上可用: for Python…

195:vue+openlayers 加载json格式热力图,调节半径大小和模糊程度

第195个 点击查看专栏目录 本示例的目的是介绍演示如何在vue+openlayers中加载JSON格式的数据,呈现热力图。这里可以调节热力图的半径大小和模糊程度。 直接复制下面的 vue+openlayers源代码,操作2分钟即可运行实现效果 文章目录 示例效果配置方式示例代码(共100行)headDa…

【JavaGuide面试总结】Java高级特性基础篇·上

【JavaGuide面试总结】Java高级特性基础篇上1.为什么 Java 中只有值传递&#xff1f;2.static 关键字使用场景3.Exception 和 Error 有什么区别&#xff1f;4.Checked Exception 和 Unchecked Exception 有什么区别&#xff1f;5.Throwable 类常用方法有哪些&#xff1f;6.fina…

【Linux】缓冲区理解

​&#x1f320; 作者&#xff1a;阿亮joy. &#x1f386;专栏&#xff1a;《学会Linux》 &#x1f387; 座右铭&#xff1a;每个优秀的人都有一段沉默的时光&#xff0c;那段时光是付出了很多努力却得不到结果的日子&#xff0c;我们把它叫做扎根 目录&#x1f449;缓冲区&am…

深入理解ECAPA-TDNN——兼谈Res2Net、ASP统计池化、SENet、Batch Normalization

概述 ECAPA-TDNN是说话人识别中基于TDNN的神经网络&#xff0c;是目前最好的单体模型之一关于TDNN&#xff0c;可以参考深入理解TDNN&#xff08;Time Delay Neural Network&#xff09;——兼谈x-vector网络结构 ECAPA-TDNN TDNN本质上是1维卷积&#xff0c;而且常常是1维膨…

【Django项目开发】角色管理模块的开发(八)

文章目录一、序列化器设计1、嵌套的序列化器设计2、普通的序列化类支持&#xff1a;新增、修改角色名、删除、查询3、用于给某一个角色批量授权的序列化4、用于给某一个角色单一授权&#xff0c;包括取消单一授权二、视图类设计1、包含的接口有哪些2、set_permission_to_role方…

听说……国产的领航辅助驾驶系统都很卷?

什么是城市NOA功能&#xff1f; 基于国产芯片的城市NOA功能有看点吗&#xff1f; 国产芯片发展到了什么阶段&#xff1f; 车上配的激光雷达是不是越多越好&#xff1f; 车企常吹的“数据驱动”、“中央计算” 究竟是真是假&#xff1f; ……最近&#xff0c;两家中国公司组CP 推…

基于ros将文件夹中的图像转换为bag包(c++版本)

一、前期工作创建工作空间 二、创建工作包 创建完成后&#xff0c;文件夹的格式为&#xff1a; 三、准备编译文件和代码 3.1 更换编译文件中的内容 将上图中的&#xff0c;CMakeLists.txt文件中的内容&#xff0c;替换为下面的内容 cmake_minimum_required(VERSION 3.0.2) p…

【漏洞复现】Yapi接口管理平台RCE漏洞汇总

文章目录前言YApi接口管理平台远程代码执行漏洞一、漏洞描述二、影响版本三、FOFA语句四、漏洞复现五、修复建议YApi NoSQL注入导致远程命令执行漏洞一、YApi介绍二、漏洞描述三、漏洞分析四、漏洞详情五、影响版本六、漏洞复现七、修复建议前言 本篇文章主要归纳总结YApi各版…

南邮数据结构

md文档网址&#xff1a;https://gitee.com/infiniteStars/wang-dao-408-notes/blob/master/408/数据结构.md 1 绪论 1.1算法的基本概念 程序与算法的区别和联系 联系&#xff1a;程序是计算机指令的有序集合&#xff0c;是算法用某种程序设计语言的表述&#xff0c;是算法在…

2023年如何搭建最小可行性的产品文档/产品手册?

在推出并击败竞争对手进入市场的竞赛中&#xff0c;很容易将“不必要的”任务&#xff08;如文档&#xff09;放在次要位置。但根据 Write the Docs 纪录片社区的说法&#xff0c;文档应该既是先导性的&#xff0c;也是参与性的。这意味着您应该在开始开发之前开始记录&#xf…

吊打高斯模糊的stackBlur加入OpenCV

stackBlur介绍 stackBlur 最近才加入到OpenCV中&#xff0c;将在下一个Relase版本&#xff08;4.7&#xff09;中出现。C用户可以尝试从源码编译OpenCV体验一下。Python 用户可以尝试用pip安装rolling版本的OpenCV&#xff1a; pip install opencv-python-rolling4.6.0.202210…