Javascript常见算法详解
在JavaScript(JS)中,常见的算法涵盖了多个领域,从基础的数组操作到更复杂的排序、搜索和数据结构算法。下面是一些在JS中常见的算法示例:
1. 排序算法

Java排序算法-CSDN博客
- 冒泡排序(Bubble Sort):通过重复遍历要排序的数列,比较每对相邻元素的值,若发现顺序错误则交换之。应用场景:冒泡排序由于其实现简单,适合小规模数据或基本有序的数据排序。
function bubbleSort(arr) { const len = arr.length; for (let i = 0; i < len - 1; i++) { for (let j = 0; j < len - i - 1; j++) { if (arr[j] > arr[j + 1]) { [arr[j], arr[j + 1]] = [arr[j + 1], arr[j]]; } } } return arr;
}
const nums = [4, 5, 2, 7, 8];
console.log(bubbleSort(nums)); // [2, 4, 5, 7, 8]
- 选择排序(Selection Sort):在要排序的一组数中,选出最小(或最大)的一个数与第一个位置的数交换;然后在剩下的数当中再找最小(或最大)的与第二个位置的数交换,依此类推。应用场景:选择排序同样适合小规模数据的排序。
function selectionSort(arr) { const len = arr.length; for (let i = 0; i < len - 1; i++) { let minIndex = i; for (let j = i + 1; j < len; j++) { if (arr[j] < arr[minIndex]) { minIndex = j; } } [arr[i], arr[minIndex]] = [arr[minIndex], arr[i]]; } return arr;
}
const nums = [4, 5, 2, 7, 8];
console.log(selectionSort(nums)); // [2, 4, 5, 7, 8]
- 插入排序(Insertion Sort):通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。小规模数据或基本有序的数据。它的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。插入排序在实现上,通常采用in-place排序(即只需用到O(1)的额外空间的排序),因而在从后向前扫描过程中,找到排序位置后,需要将已排序元素逐步向后挪位,为新元素提供插入空间。
function insertionSort(arr) { for (let i = 1; i < arr.length; i++) { let key = arr[i]; // 当前需要插入的元素 let j = i - 1; // 将大于key的元素向后移动一位 while (j >= 0 && arr[j] > key) { arr[j + 1] = arr[j]; j = j - 1; } arr[j + 1] = key; // 插入key到正确的位置 } return arr;
} // 示例
const nums = [12, 11, 13, 5, 6];
console.log(insertionSort(nums)); // 输出: [5, 6, 11, 12, 13]
- 归并排序(Merge Sort):分治法的一个典型应用,将已有序的子序列合并,得到完全有序的序列。它将一个数组分成两半,对每半部分递归地应用归并排序,然后将排序好的两半合并成一个有序数组。归并排序的主要优点是稳定、效率高(平均和最坏时间复杂度均为O(n log n)),并且易于实现并行化。
function mergeSort(arr) { if (arr.length < 2) { // 基本情况:如果数组只有一个元素或为空,则直接返回该数组 return arr; } // 找到中间位置,将数组分成两部分 const middle = Math.floor(arr.length / 2); const left = arr.slice(0, middle); const right = arr.slice(middle); // 递归地对左右两部分进行归并排序 return merge(mergeSort(left), mergeSort(right));
} function merge(left, right) { let result = [], leftIndex = 0, rightIndex = 0; // 当左右两部分都还有元素时,比较并合并 while (leftIndex < left.length && rightIndex < right.length) { if (left[leftIndex] < right[rightIndex]) { result.push(left[leftIndex]); leftIndex++; } else { result.push(right[rightIndex]); rightIndex++; } } // 如果左部分还有剩余元素,则将它们添加到结果数组中 while (leftIndex < left.length) { result.push(left[leftIndex]); leftIndex++; } // 如果右部分还有剩余元素,则将它们添加到结果数组中 while (rightIndex < right.length) { result.push(right[rightIndex]); rightIndex++; } return result;
} // 示例
const nums = [38, 27, 43, 3, 9, 82, 10];
console.log(mergeSort(nums)); // 输出: [3, 9, 10, 27, 38, 43, 82]
- 快速排序(Quick Sort):是一种高效的排序算法,采用分而治之的策略来把一个序列分为较小和较大的两个子序列,然后递归地排序两个子序列。在JavaScript中,快速排序的实现通常涉及选择一个“基准”元素(pivot),然后将数组分成两个子数组:一个包含所有小于基准值的元素,另一个包含所有大于基准值的元素。最后,递归地对这两个子数组进行快速排序。
。应用场景:快速排序适用于大规模数据的排序,平均时间复杂度为O(n log n)。
function quickSort(arr) { if (arr.length <= 1) { return arr; } const pivot = arr[0]; const left = []; const right = []; for (let i = 1; i < arr.length; i++) { if (arr[i] < pivot) { left.push(arr[i]); } else { right.push(arr[i]); } } return [...quickSort(left), pivot, ...quickSort(right)];
}
const nums = [4, 5, 2, 7, 8];
console.log(quickSort(nums)); // [2, 4, 5, 7, 8]
2. 搜索算法
- 线性搜索(Linear Search):逐个检查每个元素,直到找到所需的特定元素为止。
function linearSearch(arr, target) { for (let i = 0; i < arr.length; i++) { if (arr[i] === target) { // 找到目标值,返回其索引 return i; } } // 未找到目标值,返回-1 return -1;
} // 示例
const arr = [3, 5, 7, 9, 11, 13, 15];
const target = 9;
console.log(linearSearch(arr, target)); // 输出: 3 const missingTarget = 10;
console.log(linearSearch(arr, missingTarget)); // 输出: -1
- 二分搜索(Binary Search):在有序数组中查找某一特定元素的搜索算法,搜索过程从数组的中间元素开始,如果中间元素正好是要查找的元素,则搜索过程结束;如果某一特定元素大于或者小于中间元素,则在数组大于或小于中间元素的那一半中查找,而且跟开始一样从中间元素开始比较。
function binarySearch(arr, target) { let left = 0; let right = arr.length - 1; while (left <= right) { let mid = Math.floor((left + right) / 2); if (arr[mid] === target) { // 找到目标值,返回其索引 return mid; } else if (arr[mid] < target) { // 目标值在中间值的右侧,调整左边界 left = mid + 1; } else { // 目标值在中间值的左侧,调整右边界 right = mid - 1; } } // 未找到目标值,返回-1 return -1;
} // 示例
const arr = [1, 3, 5, 7, 9, 11, 13, 15, 17, 19];
const target = 7;
console.log(binarySearch(arr, target)); // 输出: 3 const missingTarget = 10;
console.log(binarySearch(arr, missingTarget)); // 输出: -1
3. 数组和字符串操作
- 反转数组:通过交换首尾元素的方式实现。
反转数组是一个基础且常见的算法问题,可以通过多种编程语言实现。在JavaScript中,我们已经知道有一个内置的reverse()方法可以直接用来反转数组,但如果你想要自己实现一个反转数组的算法,你可以通过交换数组的首尾元素,然后向中心移动,直到到达数组的中间位置。
下面是一个使用JavaScript实现的反转数组算法的例子:
function reverseArray(arr) { let left = 0; // 左指针 let right = arr.length - 1; // 右指针 while (left < right) { // 交换左右指针所指的元素 let temp = arr[left]; arr[left] = arr[right]; arr[right] = temp; // 移动指针 left++; right--; } // 由于是在原数组上进行操作,所以不需要返回新的数组 // 但为了演示,我们可以返回原数组或者null,表示操作已完成 return arr;
} // 示例
let arr = [1, 2, 3, 4, 5];
reverseArray(arr);
console.log(arr); // 输出: [5, 4, 3, 2, 1]
这个算法的时间复杂度是O(n/2),但通常我们将其简化为O(n),因为n/2和n在算法分析中属于同一数量级。空间复杂度是O(1),因为我们只是使用了常量级别的额外空间(几个变量)来执行操作,而没有使用与输入规模成比例的额外空间。
需要注意的是,这个算法直接修改了原数组。如果你不想修改原数组,你可以先复制一份数组,然后在复制的数组上进行反转操作。例如:
function reverseArrayWithoutMutating(arr) { let copy = [...arr]; // 使用扩展运算符创建数组的一份浅拷贝 let left = 0; let right = copy.length - 1; while (left < right) { let temp = copy[left]; copy[left] = copy[right]; copy[right] = temp; left++; right--; } return copy; // 返回反转后的新数组
} // 示例
let arr = [1, 2, 3, 4, 5];
let reversedArr = reverseArrayWithoutMutating(arr);
console.log(reversedArr); // 输出: [5, 4, 3, 2, 1]
console.log(arr); // 输出: [1, 2, 3, 4, 5](原数组未改变)
- 字符串去重:使用
Set或遍历字符串,利用对象记录字符出现情况,实现去重。
function uniqueCharsInOrder(str) { // 创建一个 Set 对象,用于存储已经遇到的字符 let seen = new Set(); // 初始化一个空字符串,用于存放去重后的结果 let result = ''; // 遍历原字符串中的每个字符 for (let char of str) { // 检查当前字符是否已经在 Set 中 if (!seen.has(char)) { // 如果没有,则将其添加到 Set 中,并追加到结果字符串的末尾 seen.add(char); result += char; } // 如果字符已经在 Set 中,则跳过它,不添加到结果字符串中 } // 返回去重后且保持原始顺序的字符串 return result;
} // 示例
console.log(uniqueCharsInOrder('hello world!')); // 输出: "helo wrd!"
- 子字符串搜索:使用
indexOf或includes等方法。
indexOf() 方法
indexOf() 方法用于返回在父字符串中首次出现的子字符串的索引,如果没有找到则返回 -1。这个方法对于需要知道子字符串具体位置的场景非常有用。
let str = "Hello, world!";
let index = str.indexOf("world");
console.log(index); // 输出: 7 let fromIndex = 8;
let notFoundIndex = str.indexOf("world", fromIndex);
console.log(notFoundIndex); // 输出: -1,因为从索引8开始找不到"world"
includes() 方法
includes() 方法用于判断一个字符串是否包含在另一个字符串中,根据情况返回 true 或 false。这个方法对于只需要知道子字符串是否存在,而不需要知道其位置的场景很有用。
let str = "Hello, world!";
let found = str.includes("world");
console.log(found); // 输出: true let notFound = str.includes("universe");
console.log(notFound); // 输出: false let fromPosition = 7;
let foundAtPosition = str.includes("world", fromPosition);
console.log(foundAtPosition); // 输出: true,即使起始位置是7,"world"依然从该位置开始 // 注意:如果fromIndex大于字符串长度,则includes方法返回false
let fromIndexTooHigh = str.includes("world", 20);
console.log(fromIndexTooHigh); // 输出: false
4. 动态规划
- 斐波那契数列:经典的动态规划问题,每个数是前两个数的和。
- 最长公共子序列(LCS):寻找两个序列共有的最长子序列的问题。
5. 图论算法
- 深度优先搜索(DFS):沿着树的深度遍历树的节点,尽可能深地搜索树的分支。
- 广度优先搜索(BFS):从根节点开始,沿着树的宽度遍历树的节点。
6. 递归算法
递归算法在JS中非常常见,如计算阶乘、遍历文件目录等。
7. 数据结构相关算法
- 栈和队列的基本操作:如入栈(入队)、出栈(出队)、查看栈顶(队首)等。
- 链表操作:包括创建链表、添加节点、删除节点、反转链。表等
相关文章:
Javascript常见算法详解
在JavaScript(JS)中,常见的算法涵盖了多个领域,从基础的数组操作到更复杂的排序、搜索和数据结构算法。下面是一些在JS中常见的算法示例: 1. 排序算法 Java排序算法-CSDN博客 冒泡排序(Bubble Sort&#x…...
MySQL数据管理 - 查询语句
文章目录 查询数据1 查询指定列2 条件查询3 合并查询4 模糊查询5 聚合函数查询6 对值进行排序7 分组查询8 分页查询9 数据库关联查询1 内连接 INNER JOIN2 LEFT JOIN3 右连接 10 数据库子查询参考 查询数据 数据库最常用的操作就是查询,也是数据操作的基础…...
经典图论算法回顾之Bellman-Ford算法
Dijkstra最短路径算法存在的一个问题是不能处理负权图(详见:经典图论算法回顾之Dijkstra算法。今天要回顾的Bellman-Ford算法(wikipedia:Bellman–Ford algorithm)可以求出有负权图的最短路径,并可以对最短…...
LinuxC++(10):调用可执行程序
认识system函数 可以直接用system在代码中实现调用shell命令 /bin/ls -l /tmp表示执行ls -l命令,打开/tmp地址 而前面的/bin/表示这是shell命令,不可少,可以认为,/bin/后面的就是等价于shell里面输入的命令。 然后,cou…...
C语言指针·高级用法超详解(指针运算、野指针、悬空指针、void类型指针、二级以及多级指针)
目录 1. 指针的运算 2. 野指针和悬空指针 2.1 野指针 2.2 悬空指针 3. void类型指针 4. 二级指针和多级指针 4.1 命名规则 4.2 作用 4.2.1 二级指针可以操作一级指针记录的地址 4.2.2 利用二级指针获取变量中记录的数据 1. 指针的运算 文章开始前可以先了…...
SQL注入:MySQL元数据库,外网实战手工SQL注入
MySQL元数据库 MySQL的元数据库是一组特殊的数据库,用于存储MySQL服务器的元数据信息,在sql注入中较为常用为以下两种元数据库: information_schema:这个数据库包含了MySQL服务器上所有其他数据库的元数据信息。例如数据库名、表…...
接口与抽象类有什么区别
接口:只能包含抽象方法,成员变量只能是public static final 类型 是对行为的抽象 先约定再接口再实现 抽象类:包含成员变量和一般方法和抽象方法,当继承时,子类必须实现抽象类中的抽象方法...
【时时三省】unity test 测试框架 使用 code blocks 移植(核心文件:unity.c, unity_fixture.c)
山不在高,有仙则名。水不在深,有龙则灵。 ----CSDN 时时三省 目录 1,移植介绍 2,使用 Code::Blocks 17.12 创建工程 3,搬移文件入工程目录 4,更改代码 5,向工程添加文件 6,运…...
安装Docker以及安装过程中的错误解决
一、纯享版教程+操作截图 环境:centOs 7 FinalShell !!!此教程针对第一次安装docker的友友,如果已经安装过且报错的朋友,请移步报错合集。 1.卸载旧版本(无论是否安装过都建议执…...
PXE实验
实验前准备 关闭VMware的dhcp 点击 编辑 点击 虚拟网络编辑器 选择 NAT模式 将dhcp取消勾选 准备两台虚拟机 一台试验机,(网络环境正常并且有图形化的界面的rhel7) 一台测试机 init 5 --------------> 开启图形化界面 如…...
Spring - 解析 统一数据格式返回以及统一异常处理
接上篇文章的统一数据格式返回… 文章目录 1. 统一异常处理1.1 使用 2. 统一数据返回和统一异处理是怎么实现的2.1 initHandleAdapters2.2 initHandleExceptionResolvers 1. 统一异常处理 1.1 使用 统一异常处理的两个关键的注解是ControllerAdvice ExceptionHandler Contro…...
用Manim实现——计算和绘制图形下方区域
用Manim实现——计算和绘制图形下方区域 get_area 函数 get_area是一个用于计算和绘制图形下方区域的函数,常用于图形动画库(如 Manim) get_area(graph, x_rangeNone, color(ManimColor(#58C4DD),ManimColor(#83C167)), opacity0.3, bounde…...
MySQL 保姆级教程(十五): 组合查询
第 17 章 组合查询 17.1 组合查询 MySQL 允许执行多个查询(多条 SELECT 语句),并将结果作为单个查询集返回 17.2 创建组合查询 可用 UNION 操作符来组合数条 SQL 查询 17.2.1 使用 UNION 输入: SELECT user.USER FROM user UNION SELEC…...
《动手做科研》06. 如何产生新的研究想法
地址链接:《动手做科研》06. 如何产生新的研究想法 欢迎加入我的知识星球,定期分享AI论文干货知识! 导读: 提出好的研究想法是相当困难的,特别是当你刚接触一个领域时——这需要对文献中的空白有所了解。然而,产生研究想法的过程可…...
【Kubernetes】Deployment 的状态
Deployment 的状态 Deployment 控制器在整个生命周期中存在 3 3 3 种状态: 已完成(Complete)进行中(Progressing)失败(Failed) 通过观察 Deployment 的当前特征,可以判断 Deploym…...
新手学习Gazebo+ros仿真控制小车-----易错和自己理解
赵虚左老师讲的很详细,这里只是理一下思路,说下突然出现“新”概念之间的关系。 urdf文件:里面是配置模型的,既有模型的位置、尺寸、颜色,也包含复杂的物理模型信息比如:转动惯量,碰撞box大小等等ÿ…...
jdbc(mysql)
1.概述 jdbc:java database connection(java与数据库连接) java可以连接不同数据库,不同数据库连接细节不同,具体细节都由数据库自己实现 由java设计出一系列连接数据库的接口规范,然后由不同的数据库开发…...
【Linux】搜索log在哪个文件中执行的方法
在Linux中,如果你需要找到包含特定文本(比如一段log)的文件,你可以使用grep命令结合一些其他工具来实现这一目的。这里有几个方法可以帮助你找到包含特定log内容的文件。 1. 使用grep直接在特定目录或文件中搜索 如果你知道log大…...
web小游戏开发:2048(完)移动操作及动画效果
web小游戏开发:2048(完)移动操作及动画效果 添加随机数字游戏开始时的初始化显示分数移动和合并获取行列元素下标记录移动轨迹完整的 js小结添加随机数字 书接前文,我们在前边定义了一个 move 方法,暂时先往后放放。 在我们已经初始化好的界面上,我们需要先制作一个出现…...
Redis学习笔记——第20章 Lua脚本
第20章 Lua脚本 20.1 创建并修改Lua环境 20.1.1 创建Lua环境 服务器创建一个新的基本的Lua环境 20.1.2 载入函数库 修改Lua环境,载入一些库函数 20.1.3 创建redis全局表格 全局变量,支持在Lua脚本中执行redis命令 20.1.4 使用redis自制随机函数来…...
Vim 调用外部命令学习笔记
Vim 外部命令集成完全指南 文章目录 Vim 外部命令集成完全指南核心概念理解命令语法解析语法对比 常用外部命令详解文本排序与去重文本筛选与搜索高级 grep 搜索技巧文本替换与编辑字符处理高级文本处理编程语言处理其他实用命令 范围操作示例指定行范围处理复合命令示例 实用技…...
CTF show Web 红包题第六弹
提示 1.不是SQL注入 2.需要找关键源码 思路 进入页面发现是一个登录框,很难让人不联想到SQL注入,但提示都说了不是SQL注入,所以就不往这方面想了 先查看一下网页源码,发现一段JavaScript代码,有一个关键类ctfs…...
树莓派超全系列教程文档--(61)树莓派摄像头高级使用方法
树莓派摄像头高级使用方法 配置通过调谐文件来调整相机行为 使用多个摄像头安装 libcam 和 rpicam-apps依赖关系开发包 文章来源: http://raspberry.dns8844.cn/documentation 原文网址 配置 大多数用例自动工作,无需更改相机配置。但是,一…...
SpringBoot+uniapp 的 Champion 俱乐部微信小程序设计与实现,论文初版实现
摘要 本论文旨在设计并实现基于 SpringBoot 和 uniapp 的 Champion 俱乐部微信小程序,以满足俱乐部线上活动推广、会员管理、社交互动等需求。通过 SpringBoot 搭建后端服务,提供稳定高效的数据处理与业务逻辑支持;利用 uniapp 实现跨平台前…...
是否存在路径(FIFOBB算法)
题目描述 一个具有 n 个顶点e条边的无向图,该图顶点的编号依次为0到n-1且不存在顶点与自身相连的边。请使用FIFOBB算法编写程序,确定是否存在从顶点 source到顶点 destination的路径。 输入 第一行两个整数,分别表示n 和 e 的值(1…...
【Go语言基础【13】】函数、闭包、方法
文章目录 零、概述一、函数基础1、函数基础概念2、参数传递机制3、返回值特性3.1. 多返回值3.2. 命名返回值3.3. 错误处理 二、函数类型与高阶函数1. 函数类型定义2. 高阶函数(函数作为参数、返回值) 三、匿名函数与闭包1. 匿名函数(Lambda函…...
【分享】推荐一些办公小工具
1、PDF 在线转换 https://smallpdf.com/cn/pdf-tools 推荐理由:大部分的转换软件需要收费,要么功能不齐全,而开会员又用不了几次浪费钱,借用别人的又不安全。 这个网站它不需要登录或下载安装。而且提供的免费功能就能满足日常…...
Web中间件--tomcat学习
Web中间件–tomcat Java虚拟机详解 什么是JAVA虚拟机 Java虚拟机是一个抽象的计算机,它可以执行Java字节码。Java虚拟机是Java平台的一部分,Java平台由Java语言、Java API和Java虚拟机组成。Java虚拟机的主要作用是将Java字节码转换为机器代码&#x…...
android13 app的触摸问题定位分析流程
一、知识点 一般来说,触摸问题都是app层面出问题,我们可以在ViewRootImpl.java添加log的方式定位;如果是touchableRegion的计算问题,就会相对比较麻烦了,需要通过adb shell dumpsys input > input.log指令,且通过打印堆栈的方式,逐步定位问题,并找到修改方案。 问题…...
【Linux系统】Linux环境变量:系统配置的隐形指挥官
。# Linux系列 文章目录 前言一、环境变量的概念二、常见的环境变量三、环境变量特点及其相关指令3.1 环境变量的全局性3.2、环境变量的生命周期 四、环境变量的组织方式五、C语言对环境变量的操作5.1 设置环境变量:setenv5.2 删除环境变量:unsetenv5.3 遍历所有环境…...
