IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> js数据结构与算法_16_动态规划 -> 正文阅读

[数据结构与算法]js数据结构与算法_16_动态规划

认识动态规划

动态规划,听起来高大上,其实并不难,在你看完这篇博客后还可能感叹,这么简单呀!
在了解动态规划之前,我们得先谈谈递归,在我们的js里递归的本质就是在函数执行栈中调用函数,一层一层的深入,直到小问题被解决,开始回溯,最后大问题被解决;
递归虽然代码简洁,但是执行效率低下,使用动态规划设计的算法从它能解决的最简单的子问题开始,继而通过得到的解,去解决其他更复杂的子问题,直到整个问题都被解决。所有子问题的解通常被存储在一个数组里以便于访问。

动态规划案例

计算斐波那契数列

什么是斐波那契数列呢?0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, …
从第三项开始,前两项数值之和组成下一个数值;
那我想传入一个序列号,然后程序给我返回一个对应斐波那契数列中对应的值(从0开始);
先来看看递归,那真是简洁哈。

function recurFib(n) {
if (n < 2) {
return n;
}
else {
return recurFib(n-1) + recurFib(n-2);
}
}

用动态规划来试试,我们得要一个数组来存储子问题的解,空间复杂度这里就不探究了哈;

function dynFib(n) {
  if (n === 0) return n;
  if (n == 1 || n == 2) return 1;
  var val = [];
  // 将数组填充为0
  for (var i = 0; i <= n; ++i) {
    val[i] = 0;
  }
  // 初始化数组,将序列1、2位赋值,方便计算
  val[1] = 1;
  val[2] = 2;
  for (var i = 3; i <= n; ++i) {
    val[i] = val[i - 1] + val[i - 2];
  }
  return val[n - 1];
}

就是用数组保存一下已经求得到的值,不过这里下标为2的值保存的是斐波那契数列中下标为3的值,所以在返回结果时要-1;

寻找最长公共子串

另一个适合使用动态规划去解决的问题是寻找两个字符串的最长公共子串。例如,在单词“raven”和“havoc”中,最长的公共子串是“av”。
这个LCS(最长公共子串)的逻辑需要稍微的理解一下:首先两个字符串在相同下标值时比较两个值是否相等,这个容易撒,但是我们的题目是要找最长的公共子串,也就是说在比较时下标值不能固定,而且我们得要记录一下的连续相等的长度、索引,所以动态规划是不二的选择;
思路是用二维数组lcsarr来记录一下相等时的情况,假设传入的参数是 str1 和 str2;
我们将0填充到二维数组里面;
我们先取到str1[0],在依次于str2的每个值比较,相同则在lcsarr对应的位置上赋值为1;
重点来了哈,str1[1],与str2[0],比较时相同也是赋值为1,但是0后面的下标值j对应的值与str1[1]相同时,
需要在lcsarr[0][j-1]基础上加1;
也就是说如果两个字符串相应位置的字符进行了匹配,当前数组元素的值将被设置为前一次循环中数组元素保存的值加 1;
这么说有点抽象,它在二维数组中的表现就是斜着的一条线上相加,这样来记录连续相等的值,我来手画个图:
这样4就是最长的公共子串
完整代码:

function lcs(str1, str2) {
  // 1.初始化
  //   let lcsarr = new Array(str1.length).fill(new Array(str2.length).fill(0));同一个索引
  let lcsarr = new Array(str1.length);
  let max = 0;
  let index = null;

  // 2.遍历二维数组
  for (let i = 0; i < str1.length; i++) {
    lcsarr[i] = new Array(str2.length).fill(0);
    for (let j = 0; j < str2.length; j++) {
      // 2.1相等就将让temp[i][j]相对于temp[i-1][j-1]加一
      // 看看str1上一个的值和str2上一个对比的值是否一样,一样就是连续滴
      if (str1[i] == str2[j]) {
        //   2.2记录
        if (i > 0 && j > 0) {
          lcsarr[i][j] = 1 + lcsarr[i - 1][j - 1];
        } else {
          lcsarr[i][j] = 1;
        }
        //   2.3记录max,index
        if (max < lcsarr[i][j]) {
          max = lcsarr[i][j];
          index = i;
        }
      } else {
        lcsarr[i][j] = 0;
      }
    }
  }

  //3.1返回值处理
  if (index === null) return null;
  // 3.2要算上开始的位置所以要加一
  return str1.substr(index - max + 1, max);
}
let str1 = "coveccxaaae";
let str2 = "acveccxaf";
console.log(lcs(str1, str2));

这里初始化二维数组时不要像我第一次一样:let lcsarr = new Array(str1.length).fill(new Array(str2.length).fill(0))
全填充为一个相同的内存地址了;

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-04-22 19:01:27  更:2022-04-22 19:03:56 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 7:23:06-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码