当前位置: 首页 > news >正文

Javascript常见算法(二)【学习】

动态规划

  • 斐波那契数列

经典的动态规划问题,每个数是前两个数的和。

斐波那契数列(Fibonacci sequence)是一个非常著名的数列,其中每个数是前两个数的和,序列以0和1开始。在JavaScript中,有多种方式可以实现斐波那契数列,下面是一些常见的方法:

方法1:递归

递归是实现斐波那契数列最直接的方式,但它对于较大的数字来说效率很低,因为它会重复计算很多相同的值。

function fibonacciRecursive(n) {  if (n <= 1) return n;  return fibonacciRecursive(n - 1) + fibonacciRecursive(n - 2);  
}  console.log(fibonacciRecursive(10)); // 输出: 55

方法2:动态规划(使用数组)

为了避免递归中的重复计算,我们可以使用动态规划。这种方法通过存储已经计算过的值来避免重复计算。

function fibonacciDP(n) {  if (n <= 1) return n;  let fibArray = [0, 1];  for (let i = 2; i <= n; i++) {  fibArray[i] = fibArray[i - 1] + fibArray[i - 2];  }  return fibArray[n];  
}  console.log(fibonacciDP(10)); // 输出: 55

方法3:动态规划(不使用额外空间)

如果你想要进一步优化空间使用,可以不使用数组,而只保留前两个值。

function fibonacciIterative(n) {  if (n <= 1) return n;  let a = 0, b = 1, sum;  for (let i = 2; i <= n; i++) {  sum = a + b;  a = b;  b = sum;  }  return b;  
}  console.log(fibonacciIterative(10)); // 输出: 55

方法4:使用生成器

如果你想要一个可以逐个生成斐波那契数列中数字的方法,可以使用生成器。

function* fibonacciGenerator() {  let a = 0, b = 1;  while (true) {  yield a;  [a, b] = [b, a + b];  }  
}  const fibGen = fibonacciGenerator();  
for (let i = 0; i < 10; i++) {  console.log(fibGen.next().value); // 输出斐波那契数列的前10个数字  
}

 

 生成器:JavaScript:4分钟学会生成器函数_哔哩哔哩_bilibili

在JavaScript中,生成器(Generators)是一种特殊的函数,它可以暂停执行和恢复执行,并且可以通过yield关键字返回多次。生成器函数使用function*声明,而不是普通的function声明。生成器非常适合于处理异步操作或需要逐步生成值的场景。

基本用法

生成器函数返回一个迭代器对象,这个对象包含next()return()throw()等方法。调用next()方法会使生成器函数执行到下一个yield表达式,并返回包含valuedone属性的对象。valueyield表达式的结果(如果没有yield表达式,则为undefined),done是一个布尔值,表示生成器是否已经完成执行。

示例

下面是一个简单的生成器函数示例,它逐个生成数字1到3

function* generateNumbers() {  yield 1;  yield 2;  yield 3;  
}  const gen = generateNumbers();  console.log(gen.next()); // { value: 1, done: false }  
console.log(gen.next()); // { value: 2, done: false }  
console.log(gen.next()); // { value: 3, done: false }  
console.log(gen.next()); // { value: undefined, done: true }

异步生成器

从ES2018开始,JavaScript引入了异步生成器(Async Generators),允许生成器处理异步操作。异步生成器函数使用async function*声明,并且可以在yield关键字后面跟上一个Promise。

异步生成器示例

async function* asyncGenerator() {  yield Promise.resolve(1);  yield Promise.resolve(2);  yield Promise.resolve(3);  
}  const asyncGen = asyncGenerator();  async function run() {  for await (const value of asyncGen) {  console.log(value); // 依次打印 1, 2, 3  }  
}  run();

在这个示例中,asyncGenerator是一个异步生成器函数,它逐个yield出解析为数字的Promise。在run函数中,我们使用for await...of循环来遍历这个异步生成器,它能够自动处理每个yield的Promise,并在每个Promise解决后打印其值。 

525c33ceac45499da134f13f3ca2979a.png

d2091f0388f84e498a1154035721ed19.png368c62e555f8411ab243b1a3ae1f38b6.png

2420fa2b687443dcabfc5061e46daa5e.png

 

  • 最长公共子序列(LCS):

寻找两个序列共有的最长子序列的问题。

在JavaScript中,最长公共子序列(Longest Common Subsequence, LCS)是一个在计算机科学中常见的问题。它旨在找到两个序列共有的最长子序列的长度(或具体序列),这里的子序列不需要在原序列中连续出现,但保持相对顺序。

以下是一个用动态规划方法解决LCS问题的JavaScript示例,这个示例将计算并返回两个字符串的最长公共子序列的长度:

function longestCommonSubsequence(str1, str2) {  // 创建一个二维数组来保存子问题的解  // dp[i][j] 表示 str1 的前 i 个字符和 str2 的前 j 个字符的最长公共子序列的长度  const dp = new Array(str1.length + 1).fill(null).map(() => new Array(str2.length + 1).fill(0));  // 填充 dp 数组  for (let i = 1; i <= str1.length; i++) {  for (let j = 1; j <= str2.length; j++) {  if (str1[i - 1] === str2[j - 1]) {  // 如果当前字符相等,则当前位置的最长公共子序列长度等于左上方位置加一  dp[i][j] = dp[i - 1][j - 1] + 1;  } else {  // 如果当前字符不相等,则取左边和上边的最大值  dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]);  }  }  }  // dp[str1.length][str2.length] 存储了最长公共子序列的长度  return dp[str1.length][str2.length];  
}  // 示例  
console.log(longestCommonSubsequence("AGGTAB", "GXTXAYB")); // 输出 4,因为最长公共子序列是 "GTAB" 或 "GTAY"

如果你想要获取具体的最长公共子序列(而不仅仅是长度),则需要对上述算法进行一些修改,以追踪构建LCS的字符。这通常涉及到记录如何达到每个dp[i][j]值(例如,通过回溯或使用额外的空间来存储决策)。

以下是一个修改后的版本,用于获取具体的最长公共子序列:

function longestCommonSubsequenceRecursive(str1, str2, i, j, memo = {}) {  if (i === 0 || j === 0) return '';  if (memo[i] && memo[i][j] !== undefined) return memo[i][j];  if (str1[i - 1] === str2[j - 1]) {  memo[i][j] = str1[i - 1] + longestCommonSubsequenceRecursive(str1, str2, i - 1, j - 1, memo);  } else {  const left = longestCommonSubsequenceRecursive(str1, str2, i - 1, j, memo);  const up = longestCommonSubsequenceRecursive(str1, str2, i, j - 1, memo);  if (left.length > up.length) {  memo[i][j] = left;  } else {  memo[i][j] = up;  }  }  return memo[i][j];  
}  function longestCommonSubsequence(str1, str2) {  return longestCommonSubsequenceRecursive(str1, str2, str1.length, str2.length);  
}  // 示例  
console.log(longestCommonSubsequence("AGGTAB", "GXTXAYB")); // 输出 "GTAB" 或 "GTAY"(取决于递归的分支选择)

注意:第二个版本使用了递归和记忆化(memoization)来避免重复计算,这在实际应用中可以显著提高效率,特别是当输入字符串很长时。然而,它使用了额外的空间来存储中间结果。

 

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 常见中间件漏洞复现之【Jboss】!
  • React18+Vite+Eectron从入门到实战系列之一环境安装篇
  • 为Python添加模块搜索路径
  • 【ROS2】rmf_demo使用
  • IO-Link通信笔记(十七)——可任意MCU平台移植的面向对象程序设计的IO-Link从站协议栈与接口代码生成和监控上位机与便携式通信主站
  • 前缀和专题
  • 什么是云边协同?
  • 考研数一|极限的计算(笔记)
  • OGG转MP3音频格式转换:6种免费音频转换器推荐
  • Linux网络协议.之 tcp,udp,socket网络编程(三).之多进程实现并发demon
  • 通过java.netHttpURLConnection类实现java发送http请求
  • 【拓扑排序topsort】——启动!!!
  • 高清无水印视频素材哪里找?分享几个热门的高清无水印素材网站
  • html语法
  • mysql源码编译启动debug
  • 2017-08-04 前端日报
  • AzureCon上微软宣布了哪些容器相关的重磅消息
  • Centos6.8 使用rpm安装mysql5.7
  • CentOS学习笔记 - 12. Nginx搭建Centos7.5远程repo
  • JavaSE小实践1:Java爬取斗图网站的所有表情包
  • Java的Interrupt与线程中断
  • markdown编辑器简评
  • 阿里云Kubernetes容器服务上体验Knative
  • 复杂数据处理
  • 关于使用markdown的方法(引自CSDN教程)
  • 湖南卫视:中国白领因网络偷菜成当代最寂寞的人?
  • 你真的知道 == 和 equals 的区别吗?
  • 实现菜单下拉伸展折叠效果demo
  • 使用SAX解析XML
  • 世界上最简单的无等待算法(getAndIncrement)
  • 微信支付JSAPI,实测!终极方案
  • 用Node EJS写一个爬虫脚本每天定时给心爱的她发一封暖心邮件
  • 扩展资源服务器解决oauth2 性能瓶颈
  • ​LeetCode解法汇总2182. 构造限制重复的字符串
  • #LLM入门|Prompt#1.8_聊天机器人_Chatbot
  • #中的引用型是什么意识_Java中四种引用有什么区别以及应用场景
  • ( 用例图)定义了系统的功能需求,它是从系统的外部看系统功能,并不描述系统内部对功能的具体实现
  • (3)选择元素——(17)练习(Exercises)
  • (35)远程识别(又称无人机识别)(二)
  • (附源码)springboot课程在线考试系统 毕业设计 655127
  • (附源码)ssm基于jsp的在线点餐系统 毕业设计 111016
  • (转) RFS+AutoItLibrary测试web对话框
  • (转)visual stdio 书签功能介绍
  • (转)负载均衡,回话保持,cookie
  • .bat批处理出现中文乱码的情况
  • .form文件_一篇文章学会文件上传
  • .gitignore文件_Git:.gitignore
  • .md即markdown文件的基本常用编写语法
  • .Net Core与存储过程(一)
  • .NET Micro Framework初体验
  • .net MySql
  • .NET WPF 抖动动画
  • .NET 将混合了多个不同平台(Windows Mac Linux)的文件 目录的路径格式化成同一个平台下的路径
  • .NET 快速重构概要1
  • .NET8.0 AOT 经验分享 FreeSql/FreeRedis/FreeScheduler 均已通过测试