递归

为何用递归呢?更快吗?递归并不比普通版本更快,反倒更慢。但要知道,递归更容易理解,
并且它所需的代码量更少。
通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解,递归策略只需少量的程序就可描述出解题过程所需要的多次重复计算,大大地减少了程序的代码量。递归的能力在于用有限的语句来定义对象的无限集合。一般来说,递归需要有边界条件、递归前进段和递归返回段。当边界条件不满足时,递归前进;当边界条件满足时,递归返回。

(ECMAScript 6中,因为尾调用优化的缘故,递归并不会更慢。但是在其他语言中,递归通常更慢)
递归是一种解决问题的方法,它解决问题的各个小部分,直到解决最初的大问题。通常涉及函数调用自身。
每个递归函数都必须要有边界条件,即一个不再递归调用的条件(停止点),以防止无限递归。
如果忘记加上用以停止函数递归调用的边界条件,递归并不会无限地执行下
去;浏览器会抛出错误,也就是所谓的栈溢出错误(stack overflow error)。

测试浏览器上限

var i = 0;
function recursiveFn () {i++;recursiveFn(); // 尾调用
}
try {recursiveFn();
} catch (ex) {alert('i = ' + i + ' error: ' + ex);
}

ECMAScript 6有尾调用优化(tail call optimization)。
如果函数内最后一个操作是调用函数,会通过“跳转指令”(jump)
而不是“子程序调用”(subroutine call)来控制。
也就是说,在ECMAScript 6中,这里的代码可以一直执行下去。
所以,具有停止递归的边界条件非常重要。

斐波那契问题。

斐波那契数列的定义如下:
 1和2的斐波那契数是 1;
 n(n>2)的斐波那契数是(n1)的斐波那契数加上(n2)的斐波那契数

function fibonacci(num){if (num === 1 || num === 2){return 1;}return fibonacci(num - 1) + fibonacci(num - 2);
}

动态规划(Dynamic Programming,DP)

是一种将复杂问题分解成更小的子问题来解决的优化技术。

区别:
要注意动态规划和分而治之(归并排序和快速排序算法中用到的那种)是不
同的方法。分而治之方法是把问题分解成相互独立的子问题,然后组合它们的答
案,而动态规划则是将问题分解成相互依赖的子问题。

用动态规划解决问题时,要遵循三个重要步骤:
(1) 定义子问题;
(2) 实现要反复执行而解决子问题的部分(递归的步骤);
(3) 识别并求解出边界条件。

 /* 1和2的斐波那契数是 1; n(n>2)的斐波那契数是(n-1)的斐波那契数加上(n-2)的斐波那契数。*/let x = 0function fib(num) {if(num === 1 || num === 2) {return 1}x++return fib(num-1) + fib(num-2)}function fib2(num){var n1 = 1,n2 = 1,n = 1;let j = 0for (var i = 3; i<=num; i++){j++n = n1 + n2;n1 = n2;n2 = n;}console.log(`j`, j)return n;}console.time('1')console.log(fib(6))console.timeEnd('1')console.log(`x`, x)console.time('2')console.log(fib2(6))console.timeEnd('2')console.info('=====')// 动态规划更循环次数更多.时间复杂度为O(2^n)// 而简单的循环方式次数少。时间复杂度为O(n)。// 递归看情况而言,有时候是比较消耗内存,有时候是优解。// 最少硬币找零问题/* 例如,美国有以下面额(硬币):d1=1,d2=5,d3=10,d4=25。
如果要找36美分的零钱,我们可以用1个25美分、1个10美分和1个便士(1美分)。
如何将这个解答转化成算法? */// 判断条件是最难确定的。// 这里的思想是,计算每种金额组成的可能组合,并将结果进行缓存。// 比如1的可能组合,2的可能组合,...,以此类推。// 到最后也就是我们需要的那个金额的时候,// 循环里面是每次都去取得之前的可能组合回来比较并存入结果集。function MinCoinChange(coins) {let cache = {} // 缓存计算结果this.makeChange = function(amount) {let me = thisif(!amount) {return []}if(cache[amount]) {return cache[amount]}let min = []let newMinlet newAmountfor (let i = 0; i < coins.length; i++) {let coin = coins[i]          newAmount = amount - coin // 按照顺序减去一种,试验每一种装满是需要多少个if(newAmount >= 0) { // 直到最后为负数newMin = me.makeChange(newAmount) // 不断计算剩余的钱的金额的可能值,缓存起来,最后返回最小的数组值。}/* 1. 还有剩余的钱2. 最小的值的长度大于目前最小值的数组的长度或者最小值数组第一次为空的情况3. 最小值的长度并且没有剩余*//* 我们判断 newAmount 是否有效,minValue (最少硬币数)是否是最优解,// 1. newMin.length < min.length - 1,新的数组必须是长度小于旧的数组的,才会替换。// 2. newAmount == 0 的时候,刚好最小, 或者有最小的新数组// 3. newAmount 不为负数与此同时 minValue 和 newAmount 是否是合理的值*/if(newAmount>=0 && (newMin.length < min.length - 1 || !min.length) && (newMin.length || !newAmount) ) {// 有一个更优的解min = [coin].concat(newMin) // 当前的值加上最新的值console.log('new min' + min + 'for' + amount)}}return (cache[amount] = min)}}// let coins = [1, 5, 10, 25]// console.time('3')// let minCoinChange = new MinCoinChange(coins)// console.log(`MinCoinChange()`, minCoinChange.makeChange(36))// console.timeEnd('3')let coins2 = [1, 3, 4]console.time('4')let minCoinChange2 = new MinCoinChange(coins2)console.log(`MinCoinChange()`, minCoinChange2.makeChange(6))console.timeEnd('4')// 贪心算法// 循环所有金额可能值,// 内部再循环计算取得的当前金额总数得到多少次才大于或者等于总金额function TxMinCoinChange(coins) {this.makeChange = function(amount) {let change = []let total = 0// 从大到小装填for (let i = coins.length; i >= 0; i--) {const coin = coins[i];while(total + coin <= amount) {change.push(coin)total += coin}}return change}}console.time('5')let txMinCoinChange = new TxMinCoinChange(coins2)console.log(`txMinCoinChange.makeChange(6) `, txMinCoinChange.makeChange(6) )console.timeEnd('5')

js-js数据结构和算法-递归思想-斐波那契数-动态规划-贪心相关推荐

  1. C语言用递归求斐波那契数,让你发现递归的缺陷和效率瓶颈

    C语言用递归求斐波那契数,让你发现递归的缺陷和效率瓶颈 分享到: QQ空间 新浪微博 腾讯微博 豆瓣 人人网 递归是一种强有力的技巧,但和其他技巧一样,它也可能被误用. 一般需要递归解决的问题有两个特 ...

  2. Java递归求斐波那契数求猴子吃桃

    递归求斐波那契数 斐波那契数是指前两位是1,后面的数依次是其前两位的和.即1,1,2,3,5,8-给你一个 n,求其值是多少 public class recursionExercise01{//定义 ...

  3. 算法—递归生成斐波那契数列

    提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言 一.递归生成斐波那契数列 二.使用步骤 1.伪代码 2.c 总结 前言 提示:这里可以添加本文要记录的大概内容: 例如 ...

  4. 算法笔记_001:斐波那契数的多种解法(Java)

    本篇文章解决的问题来源于算法设计与分析课程的课堂作业,主要是运用多种方法来计算斐波那契数.具体问题及解法如下: 一.问题1: 问题描述:利用迭代算法寻找不超过编程环境能够支持的最大整数的斐波那契数是第 ...

  5. c语言斐波那契数列递归数组,C语言数据结构学习:递归之斐波那契数列

    自己对递归还是不太熟练,于是做的时候就很吃力,就是翻棋子直到棋盘上所有棋子的颜色一样为止,求最少翻多少次,方法是枚举递归.然后就打算先做另一道递归的题(从数组中取出n个元素的组合),但是同样在递归的问 ...

  6. 简洁笔记-Java数据结构基础(5.递归和斐波那契数列、汉诺塔)

    什么是递归 递归简单来说就是方法调用自己 例子1: 从前有座山,山里有座庙,庙里有个和尚,和尚在讲故事,从前有座山,山里有座庙,庙里有个和尚,和尚在讲故事,从前有座山.. 例子2:美女拿着自己的照片, ...

  7. 斐波那契数(动态规划和递归)

    递归写法: public class Test {public static void main(String[] args) {feibo test = new feibo();for (int n ...

  8. 每日一道算法题--leetcode 509--斐波那契数(动态规划)--python

    [题目描述] [代码思路] 自底向上的动态规划,避免了采用递归浪费空间以及重复计算. [源代码] class Solution(object):def fib(self, N):"" ...

  9. scala递归求斐波那契数列

    object RecursiveFnb {def main(args: Array[String]): Unit = {var count = BigInt(0)//1 1 2 3 5 ?printl ...

  10. 算法 | 详解斐波那契数列问题

    14天阅读挑战赛 本篇是学习了<趣学算法(第2版)> 第一章之后总结的. 上一篇讲到了等比数列求和问题,求Sn=1+2+22+23+...+263=?S_n = 1 + 2 + 2^2 + ...

最新文章

  1. .ARM.exidx
  2. 买了云服务器和域名怎么进行解析
  3. SimpleDateFormat处理 dd-MMM-yy类型日期
  4. syslog(),closelog()与openlog()--日志操作函数
  5. Docker批量操作容器
  6. springboot入门_shiro
  7. 泛型字典 0104 c#
  8. Kali Linux 网络扫描秘籍 第六章 拒绝服务(一)
  9. python airflow_airflow 简明指南
  10. 【第5篇】Python爬虫实战-读取临时邮箱内容
  11. python如何清屏_python如何清屏
  12. Android 使用低功耗蓝牙简单介绍
  13. 车辆纵向mpc控制器
  14. Nacos配置热更新的4种方式、读取项目配置文件的多种方式,@value,@RefreshScope,@NacosConfigurationProperties
  15. 发现一个可以让程序员提神的方法
  16. 在WINDOWS 10上SQL SERVER如何远程调试防火墙
  17. Excel自定义排序
  18. CPU、MCU、FPGA、SoC……这些芯片究竟是啥?
  19. P1146 硬币翻转 python题解
  20. ecshop smarty php,ecshop的smarty基础普及知识

热门文章

  1. 佳能打印机手机显示未连接服务器,佳能打印机出现服务器设置密码
  2. 6.5 发散思维能力
  3. Python3-pandas
  4. windows笔记本查看电池损耗
  5. EDP转HDMI 4K60HZ视频信号转换方案CS5263完全替代IT6563
  6. Kubernetes:(十四)安全机制(一定要做好安全措施哦)
  7. 量化交易 米筐 策略评价指标
  8. HomeKit支持matter协议,这背后将寓意着什么?
  9. ai怎么调界面大小_Adobe Illustrator(Ai)怎么改变页面大小,快捷键是什么?
  10. 信息学奥赛一本通 1296:开餐馆(evd)