ES6的JavaScript数据结构实现之分而治之,动态规划,贪心算法和回溯算法
目的:ES6标准下的JS算法的一些实现代码。(作为记录和启发)
内容:分而治之,动态规划,贪心算法,回溯算法及其著名算法问题。(未完成,待继续)
所有源码在我的Github上(如果觉得不错记得给星鼓励我哦):ES6的JavaScript算法思想实现之分而治之,动态规划,贪心算法和回溯算法(分别在divide and rule、dynamic programming、greedy、backtracking目录下)
一、基础算法
1、分而治之
概念:分而治之算法可以分为三个部分。1、分解原问题为多个子问题(原问题的多个小实例);2、解决子问题,用返回解决子问题的方式的递归算法。递归算法的基本情形可以用来解决子问题;3、组合这些子问题的解决方式,得到原问题的解。
分而治之的二分搜索算法如下:
1 | const Compare = { |
2、动态规划
概念:动态规划(dynamic programming,DP)是一种将复杂问题分解成更小的子问题来解决的优化技术(分而治之方法是把问题分解成相互独立的子问题,然后组合它们的答案;而动态规划是将问题分解成相互依赖的子问题)。用动态规划解决问题时,要遵循三个重要步骤:1、定义子问题;2、实现要反复执行来解决子问题的部分(考虑递归);3、识别并求解出基线条件。
动态规划能解决一些著名算法问题:
2.1 背包问题
描述:给出一组项,各自有值和容量,目标是找出总值最大的项的集合。这个问题的限制是,总容量必须小于等于“背包”的容量。
1 | function knapSack(capacity, weights, values, n) { |
2.2 最长公共子序列
描述:找出一组序列的最长公共子序列(可由另一序列删除元素但不改变余下元素的顺序而得到)。最长子序列是指,在两个字符串序列中以相同顺序出现,但不要求连续(非字符串子串)的字符串序列。
1 | function printSolution(solution, wordX, m, n) { |
2.3 矩阵链相乘
描述:给出一系列矩阵,目标是找到这些矩阵相乘的最高效办法(计算次数尽可能少)。相乘运算不会进行,解决方案是找到这些矩阵各自相乘的顺序(由于矩阵乘法结合律的原因)。
1 | function matrixChainOrder(p) { |
2.4 硬币找零
描述:给出面额为d1,…,dn的一定数量的硬币和要找零的钱数,找出有多少种找零的方法。
我们来研究一下最少硬币找零问题。(找出最少硬币个数的方案)
1 | function minCoinChange(coins, amount) { |
2.5 图的全源最短路径
描述:对所有顶点对(u,v),找出从顶点u到顶点v的最短路径。
用Floyd-Warshall算法:
1 | const floydWarshall = graph => { |
3、贪心算法
概念:贪心算法遵循一种近似解决问题的技术,期盼通过每个阶段的局部最优选择(当前最好的解),从而达到全局的最优(全局最优解)。它不像动态规划算法那那样计算更大的格局。
3.1最少硬币找零问题
1 | function minCoinChangeGreedy (coins, amount) { |
3.2 分数背包问题
概念:在分数背包问题中,可以装入分数的物品。
1 | function knapSackGreedy(capacity, weights, values) { |
4、回溯算法
概念:回溯是一种渐进式寻找并构建问题解决方式的策略。从一个可能的动作开始并试着用这个动作解决问题。如果不能解决,就回溯并选择另一个动作直到问题解决为止。根据这种行为,回溯算法会尝试所有可能的动作(如果更快找到了解决办法就尝试较少的次数)来解决问题。可用回溯解决的著名问题有:骑士巡逻问题,N皇后问题,迷宫老鼠问题,数独解问题。
4.1 迷宫老鼠问题
1 | function ratInAMaze(maze) { |
4.2 数独解问题
1 | function sudokuSolver(matrix) { |