阶乘与斐波那契数列的多种实现

480 阅读2分钟

世界以痛吻我,要我报之以歌

写在前面

实现这些程序,意义本身并不是很大,重要的是思考的过程。我们针对问题可能会有多种解题思路,解决方式多了,那必然就需要找出最好的,这就是算法所谓的寻找最优解。

虽然这些实现在前面的文章都已经写过了,不过我还是想简单记录下,证明我来过了,我又走了。

注:切忌眼高手低,下面直接贴代码并辅以少量说明。

阶乘

循环实现

function foo(num){
    let total = 1;
    while(num > 0){
        total *= num; 
        num--;
    }
    return total;
}

递归实现

function foo(num){
    if(num===0)	return 1;
    return num * foo(--num);
}

尾递归优化

懒人写法

function foo(num){
    function bar(){
        if(num===0)	return 1;
        return num * foo(--num);
    }
    return bar();
}

优雅的写法

function foo(num, total=1) {
    if (num === 0) return total;
    return foo(num - 1, num * total);
}

注: 说什么尾递归调用(TCO)只有 Safari 浏览器实现了,我特意安装了个测试,开启严格模式,那红色的 Error 啊,我心痛,我一直扪心自问,我安装的是假的...假的...的?就像那个号称无敌的双核谷歌浏览器???

蹦床函数实现

注: 通过蹦床函数实现函数柯里化,蹦床函数你可以理解为提供了一种将递归函数变为循环的通用方式,但有个前提:需要改写原来的递归函数。

function foo(num, total=1) {
  if (num === 0) return total;
  return foo.bind(null, num - 1, num * total);
}

function bed(fn, num){
    while(fn && fn instanceof Function){
    	fn = fn();
    }
    return fn;
}
// 使用
var a = bed(foo(4));

斐波那契数列

循环实现

function Fib(num){
    let [first, second, res] = [1, 1, 1];
    while(num > 2){
    	res = first + second;
    	first = second;
    	second = res;
    	num--;
    }
    return res;
}

递归实现

function Fib(num){
    let res = 1;
    if(num > 2)	return Fib(num-1) + Fib(num-2);
    return res;
}

迭代器实现

var Fib = {
    [Symbol.iterator](){
        let [first, second] = [0, 1];
        return {
            [Symbol.iterator](){
                return this;
            },
    	    next(){
                let temp = second;
            	second = first + second;
            	first = temp;
            	return {
            	    value: temp,
            	    done: false
            	}
            },
    	    return(val){
                console.log(`结束了`);
            	return {
                    value: val,
                    done: true
            	}
    	    }
    	}
    }
}
// 使用
for(let item of Fib){
    if(item > 50)  break;
    console.log(item);
}

生成器实现

function *Fib(){
    let [first, second] = [0, 1];
    while(true){
    	let temp = second;
    	second = first + second;
    	first = temp;
    	yield temp;
    }
}
// 使用
for(let item of Fib()){
    if(item > 50)  break;
    console.log(item);
}