前端高频算法

分析算法排序:

  • 时间复杂度: 一个算法执行所耗费的时间。

  • 空间复杂度: 运行完一个程序所需内存的大小。

  • 执行效率内存消耗稳定性 三方面入手。

 1. 排序

1.1 冒泡排序

冒泡的过程只涉及相邻数据的交换操作,所以它的空间复杂度为 O(1)。

为了保证冒泡排序算法的稳定性,当有相邻的两个元素大小相等的时候,我们不做交换,相同大小的数据在排序前后不会改变顺序。 所以冒泡排序是稳定排序算法。

最佳情况:T(n) = O(n),当数据已经是正序时。

最差情况:T(n) = O(n(2)),当数据是反序时。

平均情况:T(n) = O(n(2))。

  bubbleSort = (arr) => {if (arr.length <= 1) return arr;for (let i = 0; i < arr.length - 1; i++) {let hasChange = false;for (let j = 0; j < arr.length - 1 - i; j++) {if (arr[j] > arr[j + 1]) {const temp = arr[j];arr[j] = arr[j + 1];arr[j + 1] = temp;hasChange = true;}}if (!hasChange) return;}console.log('arr', arr)return arr;}const arr = [7, 8, 4, 5, 6, 3, 2, 1];
bubbleSort(arr);
1.2  插入排序

插入排序算法的运行并不需要额外的存储空间,所以空间复杂度是 O(1)。

在插入排序中,对于值相同的元素,我们可以选择将后面出现的元素,插入到前面出现元素的后面,这样就可以保持原有的前后顺序不变,所以插入排序是稳定的排序算法。

最佳情况:T(n) = O(n),当数据已经是正序时。

最差情况:T(n) = O(n(2)),当数据是反序时。

平均情况:T(n) = O(n(2))。

步骤

  • 从第一个元素开始,该元素可以认为已经被排序;

  • 取出下一个元素,在已经排序的元素序列中从后向前扫描;

  • 如果该元素(已排序)大于新元素,将该元素移到下一位置;

  • 重复步骤 3,直到找到已排序的元素小于或者等于新元素的位置;

  • 将新元素插入到该位置后;

  • 重复步骤 2 ~ 5。

  insertSort = (arr) => {if (arr.length <= 1) return arr;let preIndex, current;for (let i = 1; i < arr.length; i++) {preIndex = i - 1;current = arr[i];while (preIndex >= 0 && arr[preIndex] > current) {arr[preIndex + 1] = arr[preIndex];preIndex--;}if (preIndex + 1 !== i) {arr[preIndex + 1] = current;}}console.log('arr', arr)return arr;}
优化插入排序:折半插入
  • 取 0 ~ i-1 的中间点 ( m = (i-1) >> 1 ),array[i] 与 array[m] 进行比较,若 array[i] < array[m],则说明待插入的元素 array[i] 应该处于数组的 0 ~ m 索引之间;反之,则说明它应该处于数组的 m ~ i-1 索引之间。

  • 重复步骤 1,每次缩小一半的查找范围,直至找到插入的位置。

  • 将数组中插入位置之后的元素全部后移一位。

  • 在指定位置插入第 i 个元素。

// 折半插入排序
const binaryInsertionSort = array => {const len = array.length;if (len <= 1) return;let current, i, j, low, high, m;for (i = 1; i < len; i++) {low = 0;high = i - 1;current = array[i];while (low <= high) {//步骤 1 & 2 : 折半查找
// 注: x>>1 是位运算中的右移运算, 表示右移一位, 等同于 x 除以 2 再取整, 
// 即 x>>1 == Math.floor(x/2) .m = (low + high) >> 1; if (array[i] >= array[m]) {//值相同时, 切换到高半区,保证稳定性low = m + 1; //插入点在高半区} else {high = m - 1; //插入点在低半区}}for (j = i; j > low; j--) {//步骤 3: 插入位置之后的元素全部后移一位array[j] = array[j - 1];console.log('array2 :', JSON.parse(JSON.stringify(array)));}array[low] = current; //步骤 4: 插入该元素}console.log('array2 :', JSON.parse(JSON.stringify(array)));return array;
};
 1.3 选择排序

选择排序空间复杂度为 O(1)

选择排序每次都要找剩余未排序元素中的最小值,并和前面的元素交换位置,这样破坏了稳定性。所以,选择排序是一种不稳定的排序算法。

最佳/最差/平均情况:T(n) = O(n(2))。 

步骤

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

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

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

const selectionSort = array => {const len = array.length;let minIndex, temp;for (let i = 0; i < len - 1; i++) {minIndex = i;for (let j = i + 1; j < len; j++) {if (array[j] < array[minIndex]) {// 寻找最小的数minIndex = j; // 将最小数的索引保存}}temp = array[i];array[i] = array[minIndex];array[minIndex] = temp;console.log('array: ', array);}return array;
};
1.4  快速排序

因为 partition() 函数进行分区时,不需要很多额外的内存空间,所以快排是原地排序算法。

和选择排序相似,快速排序每次交换的元素都有可能不是相邻的,因此它有可能打破原来值为相同的元素之间的顺序。因此,快速排序并不稳定

最佳情况:T(n) = O(n log n)。

最差情况:T(n) = O(n(2))。

平均情况:T(n) = O(n log n)。

步骤

  • 先找到一个基准点(一般指数组的中部),然后数组被该基准点分为两部分,依次与该基准点数据比较,如果比它小,放左边;反之,放右边。

  • 左右分别用一个空数组去存储比较后的数据。

  • 最后递归执行上述操作,直到数组长度 <= 1;

特点:快速,常用。

缺点:需要另外声明两个数组,浪费了内存空间资源。

const quickSort1 = arr => {if (arr.length <= 1) {return arr;}//取基准点const midIndex = Math.floor(arr.length / 2);//取基准点的值,splice(index,1) 则返回的是含有被删除的元素的数组。const valArr = arr.splice(midIndex, 1);const midIndexVal = valArr[0];const left = []; //存放比基准点小的数组const right = []; //存放比基准点大的数组// 遍历数组,进行判断分配// 递归动态数组不要用len=arr.length替换arr.lengthfor (let i = 0; i < arr.length; i++) { if (arr[i] < midIndexVal) {left.push(arr[i]); //比基准点小的放在左边数组} else {right.push(arr[i]); //比基准点大的放在右边数组}}//递归执行以上操作,对左右两个数组进行操作,直到数组长度为 <= 1return quickSort1(left).concat(midIndexVal, quickSort1(right));
};
const array2 = [5, 4, 3, 2, 1];
console.log('quickSort1 ', quickSort1(array2));
// quickSort1: [1, 2, 3, 4, 5]
1.5 希尔排序

空间复杂度为 O(1)

希尔排序不稳定

最佳情况:T(n) = O(n log n)。

最差情况:T(n) = O(n log(2) n)。

平均情况:T(n) = O(n log(2) n)。

const shellSort = arr => {let len = arr.length,temp,gap = 1;console.time('希尔排序耗时');while (gap < len / 3) {//动态定义间隔序列gap = gap * 3 + 1;}for (gap; gap > 0; gap = Math.floor(gap / 3)) {for (let i = gap; i < len; i++) {temp = arr[i];let j = i - gap;for (; j >= 0 && arr[j] > temp; j -= gap) {arr[j + gap] = arr[j];}arr[j + gap] = temp;console.log('arr  :', arr);}}console.timeEnd('希尔排序耗时');return arr;
};
2. 动态规划 
2.1 斐波拉契数列

0,1,1,2,3,5,8,13,21,34,55,......

function fibo (n) {if (n <= 0)  return 0;if (n === 1) return 1;return fibo(n - 1) + fibo(n - 2);
}优化之后function fibo (n) {if (n <= 0) return 0;if (n <= 1) return 1;var res, a = 0, b = 1;for (var i = 2; i <= n; i++) {res = a + b;a = b;b = res;}return res;
}
2.2  寻找最长公共字串
function maxSubString (str1, str2) {if (!str1 || !str2) return '';var len1 = str1.length,len2 = str2.length;var maxSubStr = '';for (var i = 0; i < len1; i++) {for (var j = 0; j < len2; j++) {var tempStr = '',k = 0;while ((i + k < len1) && (j + k < len2) && (str1[i + k] === str2[j + k])) {tempStr += str1[i + k];k++;}if (tempStr.length >  maxSubStr.length) {maxSubStr = tempStr;}}}return maxSubStr;
}
2.3  背包问题 

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

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

相关文章

政安晨:【Keras机器学习示例演绎】(二十八)—— 使用 卷积神经网络与循环神经网络 架构进行视频分类

目录 数据收集 设置 定义超参数 数据准备 序列模型 推论 政安晨的个人主页&#xff1a;政安晨 欢迎 &#x1f44d;点赞✍评论⭐收藏 收录专栏: TensorFlow与Keras机器学习实战 希望政安晨的博客能够对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出指正…

AIGC笔记--Diffuser的基本使用

目录 1--加载模型 2--半精度推理 3--固定随机种子 4--更改扩散步数 5--设置negative_prompt 1--加载模型 以下代码使用 from_pretrained() 来加载预训练模型&#xff0c;使用参数cache_dir来指定下载模型的存储地址&#xff1b; from diffusers import DiffusionPipeline,…

分享自己一篇在亚马逊云科技AWS官网发的Blog技术文章

小李哥在亚马逊AWS官网&#xff0c;作为第一作者发了自己的第一篇AWS Blog文章&#xff0c;也是自己今年在AWS官网的第11篇文章。文章主要内容是描述为出海的金融企业&#xff0c;搭建满足PCI-DSS合规、FIPS 140-2 Level 3安全标准的传输中数据加密云端方案&#xff0c;主要用于…

江苏省建设工程专业技术资格条件

江苏省建设工程专业技术资格条件评审文件链接江苏省人力资源和社会保障厅 人才人事 省专业技术人员职称&#xff08;职业资格&#xff09;工作领导小组 关于印发《江苏省建设工程专业技术资格条件&#xff08;试行&#xff09;》的通知评审工作的通知江苏省人力资源和社会保障厅…

【补充】1-auth的使用、扩写auth的user表、django支持缓存

1 Auth的使用 1.1 扩写auth的user表 2 缓存 1 Auth的使用 # django 的一个app---》用户的登录&#xff0c;退出&#xff0c;注册。。。# 配置文件中配置&#xff1a;---》表会被迁移INSTALLED_APPS [django.contrib.auth,]# auth有哪些表---权限控制&#xff1a;-Permission&a…

更深层次理解传输层两协议【UDP | TCP】【UDP 缓冲区 | TCP 8种策略 | 三次握手四次挥手】

博客主页&#xff1a;花果山~程序猿-CSDN博客 文章分栏&#xff1a;Linux_花果山~程序猿的博客-CSDN博客 关注我一起学习&#xff0c;一起进步&#xff0c;一起探索编程的无限可能吧&#xff01;让我们一起努力&#xff0c;一起成长&#xff01; 目录 再谈端口号 端口号的返回…

ML system 入坑指南

ML system 入坑指南 | 摸黑干活 最近ChatGpt大火,越来越多开始关注大模型2,但对于大模型落地而言,除了先进的算法,其背后的MLsystem(机器学习系统), 从分布式训练到高效推理的完整链路同样重要, 好的基础设施是应用爆发的基础. 作为一个入坑MLsys快两年半的练习生, 本文主要围…

jsp驾校管理系统Myeclipse开发mysql数据库web结构java编程计算机网页项目

一、源码特点 JSP 驾校管理系统 是一套完善的web设计系统&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统采用serlvetdaobean mvc 模式&#xff0c;系统主要采用B/S模式开发。开发环境为TOMCAT7.0,Myeclipse8.5开发…

C#面:ASP.NET 的身份验证方式有哪些

C# ASP.NET 提供了多种身份验证方式&#xff0c;常用的有以下几种&#xff1a; Forms 身份验证&#xff1a;Forms 身份验证是 ASP.NET 中最常用的身份验证方式之一。它基于 cookie来跟踪用户的身份认证状态。在 Forms 身份验证中&#xff0c;用户在登录页面输入用户名和密码后…

解码Starknet Verifier:深入逆向工程之旅

1. 引言 Sandstorm为&#xff1a; 能提交独立proof给StarkWare的Ethereum Verifier&#xff0c;的首个开源的STARK prover。 开源代码见&#xff1a; https://github.com/andrewmilson/sandstorm&#xff08;Rust&#xff09; L2Beat 提供了以太坊上Starknet的合约架构图&…

单机多GPU的训练及debug中vscode下launch.json内容设置

1.预配置 Local_rank:当前机子上的第几块GPU。这里设置为-1&#xff0c;后续多线程自动分配显卡。 Cuda_visible_devices:指定分配资源到几块显卡上&#xff0c;这里‘0&#xff0c;1&#xff0c;2&#xff0c;3’就是这四张gpu的id。 os.environ[LOCAL_RANK] -1 os.enviro…

rust可变全局静态数组用法

extern crate alloc; use alloc::vec::Vec; use core::mem::ManuallyDrop; use log::info; use uefi::println; pub static mut gbuf:&static mut [i32] &mut [0; 0x1000]; pub fn testdumphex() -> i32 { info!(“testdumphex!”); let mut hexvec Vec::new();…

农村公交与异构无人机协同配送优化

针对农村公交与异构无人机协同配送的优化问题,可以从以下几个方面进行探讨: 1. 融合公交与无人机配送 公交物流体系:利用农村公交网络,建立以公交车辆为基础的物流配送体系。公交车辆可以沿途收集或投递货物,提高物流配送效率。无人机辅助配送:在公交物流体系的基础上,…

Linux学习系列文件管理之输出与重定向

在 Linux 中有三个经常用到的输入输出流&#xff0c;他们分别是&#xff1a; 标准输入&#xff08;stdin&#xff09;标准输出&#xff08;stdout&#xff09;标准错误&#xff08;stderr&#xff09; 在 Linux 系统中&#xff0c;系统保留了 0&#xff08;标准输入&#xff…

C语言/数据结构——每日一题(反转链表)

一.前言 大家好&#xff01;今天又是每日一题环节。今天我为大家分享了一道单链表题——反转链表。 废话不多说&#xff0c;让我们直接进入正题吧。 二.正文 1.1题目信息 这是一道leetCode上面的一道题&#xff1a;https://leetcode.cn/problems/reverse-linked-list 1.2解…

2.2 Java全栈开发前端+后端(全栈工程师进阶之路)-前端框架VUE3-基础-Vue基本语法

文本渲染指令 文本渲染指令-v-html与v-text Vue使用了基于HTML的模板语法&#xff0c;允许开发者声明式地将DOM绑定至底层Vue实例的数据。所有Vue的模板都是 合法的HTML&#xff0c;所以能被遵循规范的浏览器和HTML解析器解析。 在前面&#xff0c;我们一直使用的是字符串插…

Java面试八股之强软弱虚引用的概念及区别

Java中强软弱虚引用的概念及区别 在Java中&#xff0c;强引用、软引用、弱引用和虚引用是四种不同类型的引用&#xff0c;它们在对象生命周期管理、垃圾收集&#xff08;Garbage Collection, GC&#xff09;以及内存管理方面有着不同的行为和用途。以下是它们的概念和主要区别…

Java 中的自定义排序实现方法

文章目录 Java 中的自定义排序实现方法1. 使用自定义比较器对数组进行排序1.1 实现Comparator接口1.2 使用Arrays.sort()方法1.3 匿名内部类1.4 代码结果 2. 使用自定义比较器对集合进行排序2.1 实现Comparable接口2.2 使用Collections.sort()方法2.3 使用Lambda表达式2.4 代码…

2.Neo4j的搭建启动

Graph Database 图数据库 版本对应关系 官网都是高版本&#xff0c;推荐使用下载地址可以找到社区老版本&#xff1a; https://we-yun.com/doc/neo4j/ neo4j.bat 启动脚本 cypher-shell.bat 执行CQL语句的。 import文件夹可以放入excel,csv等数据文件&#xff0c;导入到…

llamaindex 中GPTVectorStoreIndex 和 VectorStoreIndex区别

在 llama_index 库中,GPTVectorStoreIndex 和 VectorStoreIndex 都是用于创建向量存储索引的类,但它们在某些方面有所不同。 底层模型: GPTVectorStoreIndex 使用 GPT (Generative Pre-trained Transformer) 模型来生成文本的向量表示。它利用 GPT 模型的上下文理解能力来捕获…