JavaScript中的常见算法
一.排序算法
1.冒泡排序
冒泡排序比较所有相邻的两个项,如果第一个比第二个大,则交换它们。元素项向上移动至 正确的顺序,就好像气泡升至表面一样。
function bubbleSort(arr) {const { length } = arrfor (let i = 0; i < length - 1; i++) {for (let j = 0; j < length - i - 1; j++) {if (arr[j] > arr[j + 1]) {[arr[j], arr[j + 1]] = [arr[j + 1], arr[j]]}}}return arr
}arr = [3, 2, 5, 4, 7, 1]
console.log(bubbleSort(arr)); //[1, 2, 3, 4, 5, 7]
2.选择排序
选择排序算法是一种原址比较排序算法。选择排序大致的思路是找到数据结构中的最小值并 将其放置在第一位,接着找到第二小的值并将其放在第二位,以此类推。
function selectSort(arr) {const { length } = arrlet minfor (let i = 0; i < length - 1; i++) {min = ifor (let j = i; j < length; j++) {if (arr[j] < arr[min]) {min = j}}if (min !== i) {[arr[i], arr[min]] = [arr[min], arr[i]]}}return arr
}
3.插入排序
如图所示,只可意会不可言传
function insertSort(arr) {const { length } = arrlet tempfor (let i = 1; i < length; i++) {temp = arr[i]let j = iwhile (j > 0 && arr[j - 1] > temp) {arr[j] = arr[j - 1]j--}arr[j] = temp}return arr
}
4.归并排序
归并排序是一种分而治之算法。其思想是将原始数组切分成较小的数组,直到每个小数组只 有一个位置,接着将小数组归并成较大的数组,直到最后只有一个排序完毕的大数组。
图片详解:
function mergeSort(array) {if (array.length > 1) {const {length} = array;const middle = Math.floor(length / 2);const left = mergeSort(array.slice(0, middle));const right = mergeSort(array.slice(middle, length));array = merge(left, right);}return array;
}function merge(left, right) {let i = 0;let j = 0;const result = [];while (i < left.length && j < right.length) {result.push(left[i] < right[j] ? left[i++] : right[j++]);console.log(result)//先push ,再++}return result.concat(i < left.length ? left.slice(i) : right.slice(j));
}
例如,如果
left = [3, 4]
和right = [1, 2]
,那么merge
函数会按以下步骤操作:
- 比较
left[0]
和right[0]
(3 和 1),因为 1 < 3,所以将 1 添加到result
,打印[1]
。- 然后比较
left[0]
和right[1]
(3 和 2),因为 2 < 3,所以将 2 添加到result
,打印[1, 2]
。- 由于
right
已经被完全遍历,将left
剩余的元素(3 和 4)添加到result
,最终result
为[1, 2, 3, 4]
。
5.快速排序
确立基准元素,根据其它元素与基准元素的大小比较,大的分为一组,小的分为一组,再在连接字符串的时候递归调用相应的方法,直至碰到递归调用的结束条件。
function quickSort(arr) {const { length } = arr//结束条件if (length < 2) {return arr}let base = arr[0]let minArr = arr.slice(1).filter(item => item <= base)let maxArr = arr.slice(1).filter(item => item >= base)return quickSort(minArr).concat(base).concat(quickSort(maxArr))
}
6.计数排序
计数排序使用一个用来存储每个元素在原始数组中出现次数的临时数组。在所有元素都计数完成后,临时数组已排好序并可迭代以构建排序 后的结果数组。
//缺点是浪费数组空间,最好是在要排序的数字比较连续紧凑的时候使用
function countSort(arr) {if (arr.length < 2) {return arr}const maxValue = Math.max(...arr)const counts = new Array(maxValue + 1)//让数组的值作为新数组的索引值,再进行计数arr.forEach(item => {if (!counts[item]) {counts[item] = 0}counts[item]++});let newArr = []let sortIndex = 0counts.forEach((item, index) => {while (item > 0) {newArr[sortIndex++] = indexitem--}})return newArr
}
7.桶排序
桶排序(也被称为箱排序)也是分布式排序算法,它将元素分为不同的桶(较小的数组), 再使用一个简单的排序算法,例如插入排序(用来排序小数组的不错的算法),来对每个桶进行 排序。然后,它将所有的桶合并为结果数组。
function bucketSort(arr, bucketSize = 3) {if (arr.length < 2) {return arr}//根据数字的个数和大小,以及桶的容量创建数量合适的桶,将各数字分配到相应的桶里const buckets = createBuckets(arr, bucketSize)//调用相应的方法并返回成功排序了的数组return sortBucketsElement(buckets)
}function createBuckets(arr, bucketSize) {let maxValue = Math.max(...arr)let minValue = Math.min(...arr)const bucketCount = Math.floor((maxValue - minValue) / bucketSize) + 1const buckets = [...Array(bucketCount)].map(() => [])for (let i = 0; i < arr.length; i++) {const bucketIndex = Math.floor((maxValue - minValue) / bucketSize)buckets[bucketIndex].push(arr[i])}return buckets
}function sortBucketsElement(buckets) {const sortArr = []for (let i = 0; i < buckets.length; i++) {if (buckets[i]) {let newBucket = insertSort(buckets[i])sortArr.push(...newBucket)}}return sortArr}function insertSort(arr) {const { length } = arrlet tempfor (let i = 1; i < length; i++) {temp = arr[i]let j = iwhile (j > 0 && arr[j - 1] > temp) {arr[j] = arr[j - 1]j--}arr[j] = temp}return arr
}console.log(bucketSort([5, 4, 3, 2, 6, 1, 7, 10, 9, 8]));//[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
8. 基数排序
基数排序也是一个分布式排序算法,它根据数字的有效位或基数(这也是它为什么叫基数排 序)将整数分布到桶中。简单来说是根据最大数的位数来确定排序的次数,排序的时候分别从个位,十位,百位等分别进行排序。
function radixSort(arr) {const base = 10let divider = 1let max = Math.max(...arr)while (divider <= max) {const buckets = [...Array(10)].map(() => [])for (let i of arr) {buckets[Math.floor(i / divider) % base].push(i)}arr = [].concat(...buckets)console.log(arr);divider *= 10}return arr
}
二.搜索算法
1.顺序搜索
顺序或线性搜索是最基本的搜索算法。它的机制是,将每一个数据结构中的元素和我们要找 的元素做比较。顺序搜索是最低效的一种搜索算法。
function search(arr, value) {for (let i = 0; i < arr.length; i++) {if (value === arr[i]) {return i}}return -1
}
2. 二分搜索
function binarySearch(find, arr, start, end) {start = start || 0end = end || arr.length - 1arr = quickSort(arr)if (start <= end && find >= arr[start] && find <= arr[end]) {if (find === arr[start]) {return start}if (find === arr[end]) {return end}let mid = Math.ceil((start + end) / 2)if (arr[mid] === find) {return mid} else if (arr[mid] > find) {return binarySearch(find, arr, start, mid - 1)} else {return binarySearch(find, arr, mid + 1, end)}}return -1
}function quickSort(arr) {const { length } = arrif (length < 2) {return arr}let base = arr[0]let minArr = arr.slice(1).filter(item => item <= base)let maxArr = arr.slice(1).filter(item => item >= base)return quickSort(minArr).concat(base).concat(quickSort(maxArr))
}
3.内插搜索
内插搜索是改良版的二分搜索。二分搜索总是检查 mid 位置上的值,而内插搜索可能会根 据要搜索的值检查数组中的不同地方。
//适合数值分布比较均匀的数组
function insertSearch(find, arr, start, end) {start = start || 0end = end || arr.length - 1arr = quickSort(arr)if (start <= end && find >= arr[start] && find <= arr[end]) {if (find === arr[start]) {return start}if (find === arr[end]) {return end}let mid = start + Math.floor((find - arr[start]) / (arr[end] - arr[start]) * (end - start))if (arr[mid] === find) {return mid} else if (arr[mid] > find) {return insertSearch(find, arr, start, mid - 1)} else {return insertSearch(find, arr, mid + 1, end)}}return -1
}function quickSort(arr) {const { length } = arrif (length < 2) {return arr}let base = arr[0]let minArr = arr.slice(1).filter(item => item <= base)let maxArr = arr.slice(1).filter(item => item >= base)return quickSort(minArr).concat(base).concat(quickSort(maxArr))
}
三.随机算法(洗牌算法)
迭代数组,从最后一位开始并将当前位置和一个随机位置进行交换。这个随机位置比当前位置小。这样,这个算法可以保证随机过的位置不会再被随机一次。
function shuffleArray(array) {let n = array.lengthlet randomwhile (n != 0) {//对非负数进行向下取整random = (Math.random() * n--) >>> 0;[arr[n], arr[random]] = [arr[random], arr[n]]}
}
四.算法设计
1.分而治之
分而治之算法可以分成三个部分。
(1) 分解原问题为多个子问题(原问题的多个小实例)。
(2) 解决子问题,用返回解决子问题的方式的递归算法。递归算法的基本情形可以用来解决子 问题。
(3) 组合这些子问题的解决方式,得到原问题的解。
2.动态规划
2.1背包问题
背包问题是一个组合优化问题。它可以描述如下:给定一个固定大小、能够携重量 W 的背 包,以及一组有价值和重量的物品,找出一个最佳解决方案,使得装入背包的物品总重量不超过 W,且总价值最大。
function knapSack(weights, values, w) {let n = weights.length - 1let f = [[]]for (let j = 0; j <= w; j++) {if (j < weights[0]) {f[0][j] = 0} else {f[0][j] = values[0]}}for (let j = 0; j <= w; j++) {for (let i = 1; i <= n; i++) {if (!f[i]) {f[i] = []}if (j < weights[i]) {f[i][j] = f[i - 1][j]} else {f[i][j] = Math.max(f[i - 1][j], f[i - 1][j - weights[i]] + values[i])}}}return f[n][w]
}console.log(knapSack([2, 2, 6, 5, 4], [6, 3, 5, 4, 6], 10));
2.2找出最长公共子序列
找出两个字符 串序列的最长子序列的长度。最长子序列是指,在两个字符串序列中以相同顺序出现,但不要求 连续(非字符串子串)的字符串序列。
function LCS(str1, str2) {var m = str1.lengthvar n = str2.lengthvar dp = [new Array(n + 1).fill(0)] //第一行全是0console.log(dp);for (var i = 1; i <= m; i++) { //一共有m+1行dp[i] = [0] //第一列全是0for (var j = 1; j <= n; j++) { //一共有n+1列if (str1[i - 1] === str2[j - 1]) {//注意这里,str1的第一个字符是在第二列中,因此要减1,str2同理dp[i][j] = dp[i - 1][j - 1] + 1 //对角+1} else {dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1])}}}let res = printLCS(dp, str1, str2, m, n)return dp[m][n];
}function printLCS(dp, str1, str2, i, j) {if (i === 0 || j === 0) {return ''}if (str1[i - 1] === str2[j - 1]) {return printLCS(dp, str1, str2, i - 1, j - 1) + str1[i - 1]} else {if (dp[i][j - 1] > dp[i - 1][j]) {return printLCS(dp, str1, str2, i, j - 1)} else {return printLCS(dp, str1, str2, i - 1, j)}}}console.log(LCS("abcadf", "acbaed")) //4
3.贪心算法
在对问题求解时,总是做出在当前看来是最好的选择。也就是说,不从整体最优上加以考虑,他所做出的仅是在某种意义上的局部最优解。贪心算法不是对所有问题都能得到整体最优解,但对范围相当广泛的许多问题他能产生整体最优解或者是整体最优解的近似解。
function tanxin(capacity, weights, values) {let list = []let select = []let total = 0for (let i = 0; i < weights.length; i++) {list.push({num: i + 1,weight: weights[i],value: values[i],rate: values[i] / weights[i]})}list.sort((a, b) => b.rate - a.rate) //降序for (let j = 0; j < list.length; j++) {let item = list[i]if (item.weight <= capacity) {select.push({num: item.num,weight: item.weight,value: item.value,rate: 1})total = total + item.valuecapacity = capacity - item.weight} else if (item.capacity > capacity && capacity > 0) {let rate = capacity / item.weightselect.push({num: item.num,weight: item.weight * rate,value: item.value * rate,rate})total = total + item.value * ratebreak} else {break}}return { select, total }
}
4.回溯算法
回溯法采用试错的思想,它尝试分步的去解决一个问题。在分步解决问题的过程中,当它通过尝试发现现有的分步答案不能得到有效的正确的解答的时候,它将取消上一步甚至是上几步的计算,再通过其它的可能的分步解答再次尝试寻找问题的答案。
给定一个 二维字符网格 board 和一个字符串单词 word
如果 word 存在于网格中,返回 true ;否则,返回 false
单词必须按照字母顺序,通过相邻的单元格内的字母构成
**二维数组:** board = [["A","B","C","E"],["S","F","C","S"],["A","D","E","E"]],
**目标:** word = "ABCCED"
function exist(board, word) {let row = board.length; //行let col = board[0].length; //列for (let i = 0; i < row; i++) {for (let j = 0; j < col; j++) {const ret = find(i, j, 0);if (ret) {return ret;}}}return false;function find(r, c, cur) {if (r >= row || r < 0) return false;if (c >= col || c < 0) return false;if (board[r][c] !== word[cur]) return false;if (cur == word.length - 1) return true;let letter = board[r][c];board[r][c] = null;const ret =find(r - 1, c, cur + 1) ||find(r + 1, c, cur + 1) ||find(r, c - 1, cur + 1) ||find(r, c + 1, cur + 1);//用null做标记是避免重复查找board[r][c] = letter;return ret;}
};
五.总结
还有诸多算法没有详细解读,随着自己的学习慢慢补充吧。
相关文章:

JavaScript中的常见算法
一.排序算法 1.冒泡排序 冒泡排序比较所有相邻的两个项,如果第一个比第二个大,则交换它们。元素项向上移动至 正确的顺序,就好像气泡升至表面一样。 function bubbleSort(arr) {const { length } arrfor (let i 0; i < length - 1; i)…...
桥接模式:连接抽象与实现的设计艺术
桥接模式:连接抽象与实现的设计艺术 在软件开发中,设计模式是帮助我们以优雅的方式解决问题的模板。桥接模式(Bridge Pattern)是一种结构型设计模式,它的主要目标是将抽象部分与实现部分分离,这样两者可以…...
C语言——oj刷题——字符串左旋
问题: 实现一个函数,可以左旋字符串中的k个字符。 例如: ABCD左旋一个字符得到BCDA ABCD左旋两个字符得到CDAB 实现: 当我们谈到字符串左旋时,我们指的是将字符串中的字符向左移动一定数量的位置。这个问题在编程中…...

神经网络(Nature Network)
最近接触目标检测较多,再此对最基本的神经网络知识进行补充,本博客适合想入门人工智能、其含有线性代数及高等数学基础的人群观看 1.构成 由输入层、隐藏层、输出层、激活函数、损失函数组成。 输入层:接收原始数据隐藏层:进行…...

【Unity】QFramework通用背包系统优化:使用Odin优化编辑器
前言 在学习凉鞋老师的课程《QFramework系统设计:通用背包系统》第四章时,笔者使用了Odin插件,对Item和ItemDatabase的SO文件进行了一些优化,使物品页面更加紧凑、更易拓展。 核心逻辑和功能没有改动,整体代码量减少…...
基本算法--贪心
1.简述 贪心法的效率非常高,复杂度常常为O(1),是一种局部最优的解题方法,而很多问题都需要求全局最优,,所以在使用贪心法之前需要评估是否能从局部最优推广到全局最优。 2.思路 作为算法的贪…...

13. 串口接收模块的项目应用案例
1. 使用串口来控制LED灯工作状态 使用串口发送指令到FPGA开发板,来控制第7课中第4个实验的开发板上的LED灯的工作状态。 LED灯的工作状态:让LED灯按指定的亮灭模式亮灭,亮灭模式未知,由用户指定,8个变化状态为一个循…...
Python re找到特定pattern并将此pattern重复n次
要找到字符串s中的数字,并将这些数字重复3次: import re s "abc123def456ghi789" # 找到所有的数字 numbers re.findall(r\d, s) # 重复每个数字3次 repeated_numbers [num * 3 for num in numbers] # 将重复的数字放回原位置 #…...

ChatGpt报错:We ran into an issue while authenticating you解决办法
在登录ChatGpt时报错:Oops!,We ran into an issue while authenticating you.(我们在验证您时遇到问题),记录一下解决过程。 完整报错: We ran into an issue while authenticating you. If this issue persists, please contact…...

如何从 iPhone 恢复已删除的视频:简单有效方法
无论您是在尝试释放空间时不小心删除了 iPhone 上的视频,还是在出厂时清空了手机,现在所有数据都消失了,都不要放弃。有一些方法可以恢复这些视频。 在本文中,我们将向您展示六种最有效的数据恢复方法,可以帮助您从 i…...

【python量化交易】qteasy使用教程02 - 获取和管理金融数据
qteasy教程2 - 获取并管理金融数据 qteasy教程2 - 获取并管理金融数据开始前的准备工作获取基础数据以及价格数据下载交易日历和基础数据查看股票和指数的基础数据下载沪市股票数据从本地获取股价数据生成K线图 数据类型的查找定期下载数据到本地回顾总结 qteasy教程2 - 获取并…...

数据库学习案例20240206-ORACLE NEW RAC agent and resource关系汇总。
1 集群架构图 整体集群架构图如下: 1 数据库启动顺序OHASD层面 操作系统进程init.ohasd run启动ohasd.bin init.ohasd run 集群自动启动是否被禁用 crsctl enable has/crsGIHOME所在文件系统是否被正常挂载。管道文件npohasd是否能够被访问, cd /var/t…...

TypeScript 入门
课程地址 ts 开发环境搭建 npm i -g typescript查看安装位置: $ npm root -g C:\Users\Daniel\AppData\Roaming\npm\node_modules创建 hello.ts: console.log("hello, ts");编译 ts 文件,得到 js 文件: $ tsc foo.…...
linux 磁盘相关操作
1.U盘接入虚拟机 (1)在插入u盘时,虚拟机会检测usb设备,在弹出窗口选择连接到虚拟机即可。 (2)或 直接在虚拟机--->可移动设备--->找到U盘---->连接 2.检测U盘是否被虚拟机识别 ls /dev/sd* 查…...
PyTorch: torch.max()函数详解
torch.max函数详解:基于PyTorch的深入探索 🌵文章目录🌵 🌳引言🌳🌳torch.max()函数简介🌳🌳torch.max()的返回值🌳🌳torch.max()的应用示例🌳&am…...

Rust基础拾遗--核心功能
Rust基础拾遗 前言1.所有权与移动1.1 所有权 2.引用3.特型与泛型简介3.1 使用特型3.2 特型对象3.3 泛型函数与类型参数 4.实用工具特型5.闭包 前言 通过Rust程序设计-第二版笔记的形式对Rust相关重点知识进行汇总,读者通读此系列文章就可以轻松的把该语言基础捡起来…...

MySQL:常用指令
MySQL官网 一、在Windows 系统 cmd窗口里执行的命令 启动:net start MySQL停止:net stop MySQL卸载:sc delete MySQL 二、在macOS系统终端里执行的命令 启动:mysql.server start停止:mysql.server stop重启:mysql.server restart 三、执行帮…...

Scrapy:Python中强大的网络爬虫框架
Scrapy:Python中强大的网络爬虫框架 在当今信息爆炸的时代,从互联网上获取数据已经成为许多应用程序的核心需求。Scrapy是一款基于Python的强大网络爬虫框架,它提供了一种灵活且高效的方式来提取、处理和存储互联网上的数据。本文将介绍Scrap…...
linux系统非关系型数据库redis的配置文件
redis配置文件 Redis的配置文件位于Redis安装目录下,文件名为redis.conf,配置项说明如下 Redis默认不是以守护进程的方式运行,可以通过该配置项修改,使用yes启用守护进程 daemonize no当Redis以守护进程方式运行时,Red…...

电力负荷预测 | 基于LSTM、TCN的电力负荷预测(Python)
文章目录 效果一览文章概述源码设计参考资料效果一览 文章概述 电力负荷预测 | 基于LSTM、TCN的电力负荷预测(Python) 源码设计 #------------------...

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器的上位机配置操作说明
LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器专为工业环境精心打造,完美适配AGV和无人叉车。同时,集成以太网与语音合成技术,为各类高级系统(如MES、调度系统、库位管理、立库等)提供高效便捷的语音交互体验。 L…...

AI-调查研究-01-正念冥想有用吗?对健康的影响及科学指南
点一下关注吧!!!非常感谢!!持续更新!!! 🚀 AI篇持续更新中!(长期更新) 目前2025年06月05日更新到: AI炼丹日志-28 - Aud…...
Vue记事本应用实现教程
文章目录 1. 项目介绍2. 开发环境准备3. 设计应用界面4. 创建Vue实例和数据模型5. 实现记事本功能5.1 添加新记事项5.2 删除记事项5.3 清空所有记事 6. 添加样式7. 功能扩展:显示创建时间8. 功能扩展:记事项搜索9. 完整代码10. Vue知识点解析10.1 数据绑…...
多场景 OkHttpClient 管理器 - Android 网络通信解决方案
下面是一个完整的 Android 实现,展示如何创建和管理多个 OkHttpClient 实例,分别用于长连接、普通 HTTP 请求和文件下载场景。 <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas…...

Cinnamon修改面板小工具图标
Cinnamon开始菜单-CSDN博客 设置模块都是做好的,比GNOME简单得多! 在 applet.js 里增加 const Settings imports.ui.settings;this.settings new Settings.AppletSettings(this, HTYMenusonichy, instance_id); this.settings.bind(menu-icon, menu…...
Nginx server_name 配置说明
Nginx 是一个高性能的反向代理和负载均衡服务器,其核心配置之一是 server 块中的 server_name 指令。server_name 决定了 Nginx 如何根据客户端请求的 Host 头匹配对应的虚拟主机(Virtual Host)。 1. 简介 Nginx 使用 server_name 指令来确定…...
python爬虫:Newspaper3k 的详细使用(好用的新闻网站文章抓取和解析的Python库)
更多内容请见: 爬虫和逆向教程-专栏介绍和目录 文章目录 一、Newspaper3k 概述1.1 Newspaper3k 介绍1.2 主要功能1.3 典型应用场景1.4 安装二、基本用法2.2 提取单篇文章的内容2.2 处理多篇文档三、高级选项3.1 自定义配置3.2 分析文章情感四、实战案例4.1 构建新闻摘要聚合器…...

从零开始打造 OpenSTLinux 6.6 Yocto 系统(基于STM32CubeMX)(九)
设备树移植 和uboot设备树修改的内容同步到kernel将设备树stm32mp157d-stm32mp157daa1-mx.dts复制到内核源码目录下 源码修改及编译 修改arch/arm/boot/dts/st/Makefile,新增设备树编译 stm32mp157f-ev1-m4-examples.dtb \stm32mp157d-stm32mp157daa1-mx.dtb修改…...
鱼香ros docker配置镜像报错:https://registry-1.docker.io/v2/
使用鱼香ros一件安装docker时的https://registry-1.docker.io/v2/问题 一键安装指令 wget http://fishros.com/install -O fishros && . fishros出现问题:docker pull 失败 网络不同,需要使用镜像源 按照如下步骤操作 sudo vi /etc/docker/dae…...

NLP学习路线图(二十三):长短期记忆网络(LSTM)
在自然语言处理(NLP)领域,我们时刻面临着处理序列数据的核心挑战。无论是理解句子的结构、分析文本的情感,还是实现语言的翻译,都需要模型能够捕捉词语之间依时序产生的复杂依赖关系。传统的神经网络结构在处理这种序列依赖时显得力不从心,而循环神经网络(RNN) 曾被视为…...