对于递归的傲慢与偏见

最近刷leetcode 79题 Word Search须要用到DFS算法,因为是刷leetcode,心想不能用递归,影响效率,因而利用stack完成。以后又利用递归(使用cache)实现了一次,结果居然是递归的算法比非递归更快算法

「低效」的递归

对于递归,一般会有效率低下的映像,通常是由于2点:编程

  • 重复计算
  • 函数调用开销

对于重复计算,能够缓存计算结果来解决。数组

对于函数调用开销,能够利用「尾递归」来解决,不过目前的v8引擎并无实现对尾递归的优化,因此最开始我觉得递归没有理由比非递归更快。缓存

递归与堆栈

非递归的DFS算法使用一个「堆栈」来实现。而一样,函数调用也是利用「栈」来完成。数据结构

首先,Javascipt并无原生的堆栈这个数据结构,一般是利用数组来实现,效率上应该会有所损失。函数式编程

其次,系统堆栈快于手动堆栈是没有疑问的,并且系统堆栈使用的是寄存器,比内存要快不少。函数

最后,函数调用会有额外开销这个是无法避免的,可是当函数变量很少,递归层级不深的时候,这个开销带来的效率损失不能抵消系统堆栈带来的效率提高。优化

综合来看,在不爆栈的状况下,大部分Javascript代码里使用了缓存的递归在算法效率上高于非递归算法,而且递归算法的表现力是彻底高于非递归的。不少时候,出于臆断进行的所谓优化,彻底是负优化code

关于递归的随想

以前在看SICP的时候,发现函数式编程没有循环,非函数式语言的循环操做都是利用「递归」的形式来完成的。并且全部的递归,均可以改为迭代的形式,避免了递归重复计算的缺点,也无需使用缓存来加速递归的计算,省下了缓存的开销,因此有句话叫作“全部循环都是尾递归”。递归

总结

  • 惯性思惟不可取,实践检验真理
  • 递归 !== 慢
  • 之后图的遍历、树的遍历、巴拉巴拉其它状况,直接写递归,谁怼我说递归效率低,就让他来solo。(莫名的开心咋回事儿啊?)
  • 以上关于为何递归快的推理全是推断,可是DFS非递归慢于递归是事实(Javascript中), 跪求大神给出准确解读。
相关文章
相关标签/搜索