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

news2024/12/23 12:05:35

动态规划

  • 斐波那契数列

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

斐波那契数列(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)来避免重复计算,这在实际应用中可以显著提高效率,特别是当输入字符串很长时。然而,它使用了额外的空间来存储中间结果。

 

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

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

相关文章

【数据结构】顺序表详解以及实现(C语言实现)

目录 前言&#xff1a; 顺序表的特点&#xff1a; 顺序表简介&#xff1a; 顺序表具体实现&#xff1a; 1.初始化 2.销毁 3.检查空间容量 4.头插和尾插 5.头删和尾删 6.打印 7.指定位置插入 8.指定位置删除 9. 查找是否有对应元素 顺序表是线性表的存储结构&#xff…

8月5日笔记

8月5日 nmap命令使用 nmap四种基本功能&#xff1a;端口扫描、主机探测、服务识别、系统识别。 nmap ip默认情况下&#xff0c;nmap 会对目标执行 TCP 端口扫描&#xff0c;尝试找出哪些端口是开放的&#xff0c;并提供关于这些端口上运行的服务的一些基本信息。 其他参数&…

Html5总结

前端学习 html决定页面的结构css决定页面的样式js决定页面的行为 Html5 1.文本格式化标签&#xff08;熟记&#xff09; 你在网页中&#xff0c;有时需要为文字设置粗体、斜体或下划线效果&#xff0c;这时就需要用到HTML中的文本格式化标记 2.标签属性 例如&#xff1a; …

Java SDK开发(SpringBoot Starter)

SDK开发 开发starter的好处&#xff1a;引入starter之后&#xff0c;可以在配置文件中配置&#xff0c;自动生成客户端使用。 步骤 1. 创建一个初始化SpringBoot项目&#xff0c;选择相关依赖&#xff1a; Lombook&#xff1a;日志注解 第二个注解是为了关键词提示用的&…

Java:多线程(同步死锁,锁原子变量,线程通信,线程池)

5&#xff0c;同步和死锁 5.1&#xff0c;Synchronized&#xff0c;Lock 修饰一个代码块&#xff0c;被修饰的代码块称为同步语句块&#xff0c;其作用的范围是大括号{}括起来的代码&#xff0c;作用的对象是调用这个代码块的对象&#xff1b;修饰一个方法&#xff0c;被修饰的…

如何使用极狐GitLab 实现最小权限访问?

极狐GitLab 是 GitLab 在中国的发行版&#xff0c;专门面向中国程序员和企业提供企业级一体化 DevOps 平台&#xff0c;用来帮助用户实现需求管理、源代码托管、CI/CD、安全合规&#xff0c;而且所有的操作都是在一个平台上进行&#xff0c;省事省心省钱。可以一键安装极狐GitL…

初始化seata在nacos的配置报错nacos-config.sh 127.0.0.1-nacos-config.txt-文件不存在

问题&#xff1a;初始化seata在nacos的配置报错nacos-config.sh 127.0.0.1-nacos-config.txt-文件不存在 解决思路&#xff1a; 1.seata-server-0.9.0\seata\conf下的file.conf文件要修改&#xff1a; transport {# tcp udt unix-domain-sockettype "TCP"#NIO NA…

IDEA如何去掉编辑框右侧的竖线

打开 IntelliJ Idea 软件 依次找到 File—>Settings—>Editor—>General—>Appearance 去掉勾选 Show hard wrap and visual guides (configured in Code Style options)

OpenAI 取消为 ChatGPT 加水印计划,用户反应成关键因素|TodayAI

OpenAI 近日宣布&#xff0c;尽管公司内部已经准备了一种为 ChatGPT 生成的文本添加水印的系统&#xff0c;但由于担心用户反应&#xff0c;公司决定暂不推出这一功能。 据《华尔街日报》报道&#xff0c;OpenAI 早在一年前就开发了一个可以为 ChatGPT 生成的文本添加水印的系…

智能化招聘系统:从筛选到录用的全程解析

一、引言 在数字化时代&#xff0c;企业的人力资源管理正经历着前所未有的变革。招聘作为人力资源管理的重要一环&#xff0c;其效率与精准度直接影响着企业的竞争力和发展动力。随着人工智能&#xff08;AI&#xff09;技术的飞速发展&#xff0c;智能化招聘系统应运而生&…

开源SFTP服务器软件SFTPGo

什么是 SFTPGo&#xff1f; SFTPGo 是一种事件驱动的文件传输解决方案。它支持多种协议&#xff08;SFTP、SCP、FTP/S、WebDAV、HTTP/S&#xff09;和多种存储后端&#xff0c;包括本地文件系统、加密本地文件系统、S3&#xff08;兼容&#xff09;对象存储、Google Cloud Stor…

【Linux】—— Linux进程状态(R、S、D、T、Z、X)

&#x1f30f;博客主页&#xff1a;PH_modest的博客主页 &#x1f6a9;当前专栏&#xff1a;Linux跬步积累 &#x1f48c;其他专栏&#xff1a; &#x1f534; 每日一题 &#x1f7e1; C跬步积累 &#x1f7e2; C语言跬步积累 &#x1f308;座右铭&#xff1a;广积粮&#xff0…

全新启航!阿里云向量检索服务Milvus版正式上线!

今天&#xff0c;阿里云正式宣布向量检索服务Milvus版在杭州、上海、北京、深圳四大region正式可用并开放公测&#xff01;这是由阿里云与产品生态合作伙伴Zilliz联合推出的一款业内领先的云原生向量检索引擎。向量检索服务Milvus版在上一代EMR Serverless Milvus 公测版的基础…

人工智能自动驾驶三维车道线检测—PersFormer模型代码详解

文章目录 1. 背景介绍2. 数据加载和预处理3. 模型结构4. Loss计算5. 总结和讨论 1. 背景介绍 梳理了PersFormer 3D Lane这篇论文对应的开源代码。 2. 数据加载和预处理 数据组织方式参考&#xff1a;自动驾驶三维车道线检测系列—OpenLane数据集介绍。 坐标系参考&#xff…

【Raven2靶场渗透】

文章目录 一、IP获取 二、信息收集 三、Flag1 四、漏洞利用 五、Flag2 六、Flag3 七、MSF UDF提权 八、CVE漏洞本地提权 一、IP获取 Kali IP:192.168.78.128 靶机IP&#xff1a;192.168.78.178 二、信息收集 端口和服务探测&#xff1a; nmap -sV -p- 192.168.78.178 开放…

启发式合并加树形dp

题目链接 令f【x】【0】表示不选根的x子树的最大贡献&#xff0c;f【x】【1】表示选根的x子树最大贡献&#xff0c;g【x】为max&#xff08;f【x】【0】&#xff0c;f【x】【1】&#xff09;。 如果我们要连接x和u1&#xff0c;那么贡献是&#xff1a; w【x】w【u1】f【u1】【0…

ASP.NET Core 基础 - 入门实例

一. 下载 1. 下载vs2022 Visual Studio 2022 IDE - 适用于软件开发人员的编程工具 (microsoft.com) 学生,个人开发者选择社区版就行,免费的. 安装程序一直下一步下一步就行,别忘了选择安装位置,如果都放在C盘的话,就太大了. 2. 选择工作负荷 准备工作完成 二. 创建新项目 三…

如何用密码保护你的 WordPress 管理员 (wp-admin) 目录

在维护 WordPress 网站时&#xff0c;确保 wp-admin 目录安全是非常重要的。为该目录添加密码保护可以有效提高网站安全性&#xff0c;防止未经授权的访问。这篇文章将介绍实现这一目标的两种方法。 1.为什么要为 wp-admin 目录添加密码保护 WordPress 管理员后台是网站的核心…

自动化集成应用钡铼DB系列防水分线盒

随着工业自动化的快速发展&#xff0c;如今的现场设备需要更高效、更稳定的信号采集和集成方案。钡铼技术的DB系列防水分线盒作为一种优秀的解决方案&#xff0c;成功地结合了先进的工业设计与耐用材料&#xff0c;为物流设备、食品加工设备、制药设备等多种工业应用提供了可靠…

《深入浅出WPF》学习笔记六.手动实现Mvvm

《深入浅出WPF》学习笔记六.手动实现Mvvm demo的层级结构,Mvvm常用项目结构 依赖属性基类实现 具体底层原理后续学习中再探讨,可以粗浅理解为,有一个全局对象使用list或者dic监听所有依赖属性,当一个依赖属性变化引发通知时,就会遍历查询对应的字典&#xff0c;通知View层进行…