递归概念
递归是一种针对简单循环难以编程实现的问题,通过函数调用自身,提供优雅解决方案的技术。
递归都具有以下三个要点:
使用 if-else 或 switch 语句来引导不同的情况。
拥有基础情况(base case)或终止条件(stopping condition)来停止递归。
每次递归调用都会简化原始问题,让它不断接近基础情况,所以可以用不同的参数调用自身方法,直到它变为这种基础情况。这个称之为递归调用(recursive call)。
示例,计算阶乘
if(n == 0){ // base case
return 0;
}else { // recursive call
return n * factorial(n-1)
}
递归的优势--斐波那契数列
计算阶乘很容易使用循环改写,某些情况下,用循环不容易解决的问题可以利用递归给出一个直观简单的解法。
斐波那契数列从 0 到 1 开始,之后的每个数都是序列中的前两个数之和,通过递归可以简单的实现出来。
var count = 0;
function fib(n) {
count++;
if(n == 0){
return 0;
}else if(n == 1){
return 1;
}else {
return fib(n-1) + fib(n-2);
}
}
const result = fib(10);
console.log('result',result);
console.log('count',count);
// result 55
// count 177
程序中会出现很多重复调用,求第 10 个斐波那契数,就调用了 177 次自身函数,如果尝试求出更大的斐波那契数,那么相应的调用次数就会急剧的增加。
优化递归调用
将计算过的斐波那契值存起来,可以优化递归调用。通过改良,求第 10 个斐波那契数,只调用的 11 次自身函数。而且调用自身函数的次数永远是,n + 1 次,n 代表第 n 个需求的斐波那契数。
var count = 0;
const calculated = [];
function fib(n) {
count++;
if(n == 0){
return 0;
}else if(n == 1){
return 1;
}else {
if(!calculated[n-1]){
calculated[n-1] = fib(n-1);
}
if(!calculated[n-2]){
calculated[n-2] = fib(n-2);
}
return calculated[n-1] + calculated[n-2];
}
}
const result = fib(10);
console.log('result',result);
console.log('count',count);
// result 55
// count 11
递归辅助方法
有时候可以通过找到一个要解决的初始问题的类似问题,来找到初始问题的解决方案。这个类似的方法称之为递归辅助方法。
举例,如果一个字符串从左读和从右读都是一样的,那么他就是一个回文串(palindrome)。可以通过下面的函数判断。
function palindrome(str) {
if(str.length <= 1 ){
return true;
}else if(str[0] !== str[str.length - 1]){
return false;
}else {
return palindrome(str.slice(1,-1));
}
}
const result = palindrome("dddddd");
console.log(result); // ture
每次调用 palindrome 方法时,都会使用 str.slice 来创建一个新的字符串。
为了避免重新创建字符串,使用递归辅助方法 isPalindrome 来进行改良。
function isPalindrome(str) {
return palindrome(str,0,str.length-1);
}
function palindrome(str,low,high) {
if(low >= high){
return true;
}else if(str[low] !== str[high]){
return false;
}else {
low ++;
high --;
return palindrome(str,low,high);
}
}
const result = isPalindrome("dddaaaerddd");
console.log(result); // false
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。