Comments (38)
参考实现
数学上是以递归的方法来定义
F(0) = 0;
F(1) = 1;
F(n) = F(n - 1) + F(n - 2);
- 公式版:递归
function fib(n) {
if(n < 0) throw new Error('输入的数字不能小于0');
if (n < 2) {
return n;
}
return fib(n - 1) + fib(n - 2);
}
正常递归版本是一个既简单又直接的逻辑,但是这个版本有个问题就是存在大量重复计算。如:当 n 为 5 的时候要计算fib(4) + fib(3)
当 n 为 4 的要计算fib(3) + fib(2)
,这时fib(3)
就是重复计算了。运行 fib(50)
等半天才会出结果。
- 迭代:for 循环
function fib(n) {
if(n < 0) throw new Error('输入的数字不能小于0');
let f0 = 0,
f1 = 1,
curFib = f0;
if (n < 2) {
return n;
}
for (let i = 1; i < n; i++) {
curFib = f0 + f1;
f0 = f1;
f1 = curFib;
}
return curFib;
}
这个版本没有重复计算问题,速度也明显快了很多。这并不代表循环比递归好。循环的问题在于状态变量太多,为了实现 fib 这里使用了 4 个状态变量(f0,f1,curFib,i) 而状态变量 在写、修改、删除的过程中需要格外小心。状态变量多了阅读起来也不那么优美了。
- 去除重复计算的递归版本
function fib(n) {
if(n < 0) throw new Error('输入的数字不能小于0');
if (n < 2) return n;
function _fib(n, a, b) {
if (n === 0) return a;
return _fib(n - 1, b, a + b);
}
return _fib(n, 0, 1);
}
把前两位数字做成参数巧妙的避免了重复计算,性能也有明显的提升。n 做递减运算,前两位数字做递增(斐波那契数列的递增),这段代码一个减,一个增。
- 基于 ES6 Generator 实现
function* fib(n) {
if(n < 0) throw new Error('输入的数字不能小于0');
let f0 = 1,
f1 = 1,
count = 0;
while (count < n) {
yield f0;
[f0, f1] = [f1, f0 + f1];
count++;
}
}
- 数组方法
function fib(n) {
if(n < 0) throw new Error('输入的数字不能小于0');
if (n < 2) {
return n;
}
let list = [];
list[0] = 0;
list[1] = 1;
for (let i = 1; i < n; i++) {
list[i + 1] = list[i] + list[i - 1];
}
return list[n];
}
from fe-interview.
export const fibonacci = (n: number): number => {
const base = Math.sqrt(5)
return (((1 + base) / 2) ** n - ((1 - base) / 2) ** n) / base
}
console.log(fibonacci(8))
from fe-interview.
function fabonacci(i , i1 = 1 , i2 = 1){
if(i<= 1) return i2;
return fabonacci(i -1, i2, i1 + i2)
}
from fe-interview.
function fn (n){
if(n==0) return 0
if(n==1) return 1
return fn(n-2)+fn(n-1)
}
const fn = (n)=>{
let pre = 1;
let cur = 1;
let data ;
for(var i = 3;i<=n;i++){
// 和变成当前项cur,而当前项cur会变成pre
data = pre + cur;
pre = cur
cur = data
}
return data
}
console.log(fn(2))
from fe-interview.
性能最低到50就会卡死
function fibonacci(n) {
if (n < 3) {
return 1;
}
return fibonacci(n - 2) + fibonacci(n - 1);
}
console.time("fibonacci1");
console.log(fibonacci(40));
console.timeEnd("fibonacci1");
性能大幅提升
function fibonacci2(n) {
const arr = [1, 1, 2];
const arrLen = arr.length;
if (n <= arrLen) {
return arr[n];
}
for (let i = arrLen; i < n; i++) {
arr.push(arr[i - 1] + arr[ i - 2]);
}
return arr[arr.length - 1];
}
console.time("fibonacci2");
console.log(fibonacci2(10000));
console.timeEnd("fibonacci2");
性能进一步提升
function fibonacci3(n) {
let pre1 = 1;
let pre2 = 1;
let current = 2;
if (n <= 2) {
return current;
}
for (let i = 2; i < n; i++) {
pre1 = pre2;
pre2 = current;
current = pre1 + pre2;
}
return current;
}
console.time("fibonacci2");
console.log(fibonacci3(10000));
console.timeEnd("fibonacci2");
from fe-interview.
const fibonacci = (n: number) => {
let pre = 1,
cur = 1;
if (n === 1 || n === 2) {
return 1;
}
for (let i = 3; i <= n; i++) {
[pre, cur] = [cur, pre + cur];
}
return cur;
};
console.assert(fibonacci(1) === 1);
console.assert(fibonacci(2) === 1);
console.assert(fibonacci(3) === 2);
console.assert(fibonacci(4) === 3);
from fe-interview.
function (n) {
if(n<2) return n
let a = 0,b = 1
for(let i=2;i<=n;i++){
[a, b] = [b, a+b]
}
return b
}
from fe-interview.
function fibonacci(num){
var arr = [];
for(var i = 0; i<num; i++){
if(i<2){
arr.push(1);
}else{
arr.push(arr[i-2] + arr[i-1])
}
}
return arr;
}
fibonacci(10)
//[1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
from fe-interview.
欢迎在世界发表您的优质观点
// 这是输出对应的索引值
function flat(n) {
if (n < 0) throw new Error('输入的数字不能小于0');
return Array.from({length: n + 1}).reduce((t, v, i) => (i > 1 && t.push(t[i - 1] + t[i - 2]), t), [0, 1])[n]
}
// 这是输出对应长度的数组
function flat(len = 2) {
return Array.from({length: len}).reduce((t, v, i) => (i > 1 && t.push(t[i - 1] + t[i - 2]), t), [0, 1])
}
from fe-interview.
3种方式对比
// 1.递归
// 优点:简单、易于理解
// 缺点:存在大量重复计算
function f(n) {
if (n <= 2) return 1
return f(n - 1) + f(n - 2)
}
// 2.动态规划-1
// 优点:避免了大量的重复计算
// 缺点:需要一个长度为 N 的数组空间,但其实我们只需要存储当前项的前两个值就行,所以空间可以优化到 O(1)
function f1(n) {
if (n <= 2) return 1
let dp = [1, 1]
for (let i = 2; i < n; i++) {
dp[i] = dp[i - 1] + dp[i - 2]
}
return dp[n - 1]
}
// 3.动态规划-2
// 优点:无重复计算,只需要常数个变量储存空间,空间复杂度为 O(1)
function f2(n) {
if (n <= 2) return 1
let p = 1
let q = 1
let res
for (let i = 2; i < n; i++) {
res = p + q
p = q
q = res
}
return res
}
from fe-interview.
function fibonacci(n, map = {}) {
if (n == 1 || n == 2) return n;
if (map[n]) return map[n];
let data = fibonacci(n - 1, map) + fibonacci(n - 2, map)
map[n] = data
return data
}
from fe-interview.
function fibonacci (n) {
if (!n) {
return 0
}
if(n===1 || n === 2) {
return 1
}
let num1 = 1
let num2 = 1
let num3 = 0
for (let i = 2; i < n; i++){
num3 = num1 + num2
num1 = num2
num2 = num3
}
return num3
}
时间复杂度 O(n)
from fe-interview.
使用generator
const createAry = function(args){
let handler = {
get: function(target,propKey,reciever){
return Reflect.get(target,propKey<0 ? (+propKey + target.length) : propKey,reciever)
},
set :function (target,propKey,value,reciever){
return Reflect.set(target,propKey<0 ? (+propKey + target.length) : propKey,value,reciever)
}
}
return new Proxy(args,handler)
}
var ary= createAry([1,2,3,4])
console.log(ary[-1]);
ary[-1]='a'
console.log(ary[-1]);
from fe-interview.
function fibonacci(n) {
if (n <= 1) {
return n
}
return fibonacci(n - 1) + fibonacci(n - 2)
}
fibonacci(5)
from fe-interview.
@Genzhen 写的明显有问题还那么多人点赞,笑死
from fe-interview.
@Genzhen 写的明显有问题还那么多人点赞,笑死
@cool-518 是基于ES6 Generator实现这个?输出是没有问题的
function* fib(n) {
if (n < 0) throw new Error("输入的数字不能小于0");
let f0 = 1,
f1 = 1,
count = 0;
while (count < n) {
yield f0;
[f0, f1] = [f1, f0 + f1];
count++;
}
}
for(let n of fib(10)){
console.log(n);
}
// 1 1 2 3 5 8 13 21 34 55
from fe-interview.
/**
- 求斐波那契数列第n项的值
- @param {*} n 第n项
- @param {*} map 第n项的值,缓存计算结果,防止重复计算
*/
function fibonacci(n, map = {}) {
if (n === 1 || n === 2) return n;
if (map[n]) return map[n];
// fn(n) = fn(n - 1) + fn(n - 2);
const result = fibonacii(n - 1, map) + fibonacii(n - 2, map);
map[n] = result;
return result;
}
/**
- 求斐波那契数列第n项的值
- @param {*} n 第n项
*/
function fibonacci(n) {
let pre = 1,
cur = 1,
data;
if (n === 1 || n === 2) return n;
for (let i = 3; i <= n; i++) {
data = pre + cur;
pre = cur;
cur = data;
}
return data;
}
/**
- 求斐波那契数列第0-n项的集合
- @param {*} n
*/
function fibonacci(n) {
let a = 1,
b = 1,
sum;
let arr = [1, 1];
for (let i = 3; i <= n; i++) {
sum = a + b;
a = b;
b = sum;
arr.push(sum);
}
return arr;
}
from fe-interview.
// 0,1,1,2,3,5,8,13,21
const fbnq = (num) =>
Array.from(new Array(num)).reduce((cacheArr, it, index) => {
if (index > 1) {
cacheArr.push(cacheArr[index - 2] + cacheArr[index - 1]);
} else {
cacheArr.push(index);
}
return cacheArr;
}, []);
console.log(fbnq(9));
from fe-interview.
function fabonacci(n) {
let arr = [0, 1];
for (let i = 2; i <= n; i++) {
arr.push(arr[i-2] + arr[i-1]);
}
return arr;
}
from fe-interview.
function fabonacci(n, n_1, n_2) {
if(n==1)
return n_1;
return fabonacci(n-1, n_1+n_2, n_1);
}
from fe-interview.
function fabonacci(max) {
if (max === 1 || max === 2) {
return 1;
}
return fabonacci(max - 1) + fabonacci(max - 2);
}
from fe-interview.
function fibonacci(n) {
if (n === 1) {
return 1
} else if (n === 2) {
return 1
} else {
return fibonacci(n -1) + fibonacci(n - 2)
}
}
from fe-interview.
const fibonacci = (n) => {
if(n < 3) {
return 1
}
const arr = [1, 1];
for(let x=3;x<=n;x++) {
arr.push(arr[x-2] + arr[x-3])
}
return arr[n-1];
}
from fe-interview.
function fun(length = 10, a = 0, b = 1) {
let arr = []
do {
if (arr.length < 2) {
arr.push(a)
arr.push(b)
} else {
arr.push(arr[arr.length - 2] + arr[arr.length - 1])
}
} while (arr.length < length);
return arr
}
console.log(fun(20));
// [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181]
from fe-interview.
function fibonacci(n) {
if (n < 2) return n
let a = BigInt(0), b = BigInt(1)
for (let i = 2; i <= n; i++) {
[a, b] = [b, a + b]
}
return b
}
from fe-interview.
// =============无备忘录===================
function fibonacci(n) {
if (n === 1 || n === 2) { return 1 };
return fibonacci(n - 1) + fibonacci(n - 2);
}
console.log(fibonacci(30))
// =============有备忘录===================
function fibonacci_memo(n, memo = {}) {
if (n === 1 || n === 2) return 1;
if (memo[n]) return memo[n];
let data = fibonacci_memo(n - 1, memo) + fibonacci_memo(n - 2, memo);
memo[n] = data;
return data;
}
console.log(fibonacci_memo(30))
// =============for迭代===================
function fibonacci_for(n) {
if (n === 1 || n === 2) return 1;
let total = 0, cur = 1, pre = 1;
for (let i = 3; i <= n; i++) {
total = (pre + cur);
pre = cur;
cur = total;
}
return total;
}
console.log(fibonacci_for(30))
// =============generater步进===================
function fibonacci_gen(n) {
function* gen() {
let total = 0, cur = 1, pre = 1
while (1) {
total = cur + pre;
yield total;
[cur, pre] = [total, cur];
}
}
let iterator = gen();
let data = 0;
if (n === 1 || n === 2) data = 1;
else {
for (i = 3; i <= n-1; i++) {
iterator.next();
}
data = iterator.next().value
}
return data;
}
console.log(fibonacci_gen(30))
from fe-interview.
// =============无备忘录===================
function fibonacci(n) {
if (n === 1 || n === 2) { return 1 };
return fibonacci(n - 1) + fibonacci(n - 2);
}
console.log(fibonacci(30))
// =============有备忘录===================
function fibonacci_memo(n, memo = {}) {
if (n === 1 || n === 2) return 1;
if (memo[n]) return memo[n];
let data = fibonacci_memo(n - 1, memo) + fibonacci_memo(n - 2, memo);
memo[n] = data;
return data;
}
console.log(fibonacci_memo(30))
// =============for迭代===================
function fibonacci_for(n) {
if (n === 1 || n === 2) return 1;
let total = 0, cur = 1, pre = 1;
for (let i = 3; i <= n; i++) {
total = (pre + cur);
pre = cur;
cur = total;
}
return total;
}
console.log(fibonacci_for(30))
// =============generater步进===================
function fibonacci_gen(n) {
function* gen() {
let total = 0, cur = 1, pre = 1
while (1) {
total = cur + pre;
yield total;
[cur, pre] = [total, cur];
}
}
let iterator = gen();
let data = 0;
if (n === 1 || n === 2) data = 1;
else {
for (i = 3; i <= n-1; i++) {
iterator.next();
}
data = iterator.next().value
}
return data;
}
console.log(fibonacci_gen(30))
from fe-interview.
使用generator
const createAry = function(args){ let handler = { get: function(target,propKey,reciever){ return Reflect.get(target,propKey<0 ? (+propKey + target.length) : propKey,reciever) }, set :function (target,propKey,value,reciever){ return Reflect.set(target,propKey<0 ? (+propKey + target.length) : propKey,value,reciever) } } return new Proxy(args,handler) } var ary= createAry([1,2,3,4]) console.log(ary[-1]); ary[-1]='a' console.log(ary[-1]);
答错题了兄弟
from fe-interview.
// 尾递归
function Fibonacci(n, a= 1, b= 1) {
if(n <= 1) {return b};
return Fibonacci(n - 1, b, a + b);
}
console.log(Fibonacci(10))
from fe-interview.
var fib = (n) => {
if(n <= 1) return n
return fib(n - 1) + fib(n - 2)
}
console.time('fib-1')
console.log(fib(20))
console.timeEnd('fib-1')
var fib = (n) => {
if(n <= 1) return n
fib.cache = fib.cache || {}
if(fib.cache[n]) return fib.cache[n]
fib.cache[n] = fib(n - 1) + fib(n - 2)
return fib.cache[n]
}
console.time('fib-2')
console.log(fib(20))
console.timeEnd('fib-2')
var fib = (n) => {
if(n <= 1) return n
let one = 0
let two = 1
for(let i = 2; i <= n; i++){
let o = one + two
one = two
two = o
}
return two
}
console.time('fib-3')
console.log(fib(20))
console.timeEnd('fib-3')
from fe-interview.
// 记录fib(n - 1)和fib(n-2) 避免重复计算 从下标2开始向上计算
function fib1(n) {
if (n < 0) throw new Error('输入的数字不能小于0');
if (n < 2) {
return n;
}
let f0 = 0;
let f1 = 1;
let fn = f0;
// 从下标为2开始
let i = 2;
while (i <= n) {
fn = f0 + f1;
f0 = f1;
f1 = fn;
i++;
}
return fn;
}
var n = 3;
var res1 = fib1(n);
console.log('%c res1 = %s', 'color: #007300', res1);
from fe-interview.
function fib(n) {
let [cur, acc] = [1, 1]
for (let i = 2; i < n; i++) [cur, acc] = [acc, acc + cur]
return acc
}
console.log(fib(8)) // 21
from fe-interview.
function fibonacci(length) {
var res = []
var n = 0
for (let i = 0; i < length; i++) {
res.push(n)
if(i==0) {
n=1
} else {
n=n+res[i-1]
}
}
return res
}
console.log(fibonacci(10));
from fe-interview.
我打印出一个数组
function fibonaci(n){
if(n<1){
return "err"
}
const myarray = new Array()
for (let i = 0;i<n;i++) {
if(i<=1){
myarray.push(i)
continue
}else{
let newn = myarray[i-1] + myarray[i-2]
myarray.push(newn)
}
}
return myarray
}
// 调用斐波那契方法
const newFibonaci = fibonaci(10)
console.log(newFibonaci)
from fe-interview.
这个还算稍微简单
funciton fb(n) {
if(n == 1) return 1
if(n == 2) return 1
return fb(n-1) + fb(n-2)
}
funciton fb1(n) {
if(n == 1) return 1
if(n == 2) return 1
let start=1, start1 = 1,next
for(let i = 3; i<= n;i++) {
next = start + start1
start = start1
start1 = next
}
return next
}
from fe-interview.
// 方法一:循环
function fib(n) {
let val = [0, 1];
if (n < 1) throw Error('参数n不能小于1');
if (n < 3) return val[n - 1];
for (let i = 2; i < n; i++) {
const [a, b] = val;
val = [b, a + b];
}
return val[1];
}
// 方法二:递归
function fib(n = 0, arr = [0, 1]) {
if (n < 1) throw Error('参数n不能小于1');
if (n < 3) return arr[n - 1];
const [a, b] = arr;
return fib(--n, [b, a + b]);
}
// 测试
console.log(fib(1)) // 0
console.log(fib(5)) // 3
console.log(fib(10)); // 34
// 经测试两种方法并无明显性能差别,用很大的数测试都瞬间出结果
from fe-interview.
let map = new Map();
const fbnq = (n) => {
if (map.get(n)) return map.get(n);
console.count();
if (n === 0 || n === 1) return 1;
let result = fbnq(n - 1) + fbnq(n - 2);
map.set(n, result)
return result
}
console.log(fbnq(10));
from fe-interview.
function fib(index) {
let cur = 1, next = 0, pre
while (index-- > 0) {
pre = next
next = cur + next
cur = pre
}
return next
}
//测试
for (let i = 0; i < 10; i++) {
console.log(fib(i));
}
from fe-interview.
Related Issues (20)
- Day378:说一下什么是 Http 协议无状态?怎么解决 Http 协议无状态?
- Day379:如果让你来实现一个前端监控系统,应该考虑什么?如何去实现?
- Day380:实现一个系统,统计前端页面性能、页面 JS 报错、用户操作行为、PV/UV、用户设备等消息,并进行必要的监控报警。方案如何设计,用什么技术点,什么样的系统架构,难点会在哪里? HOT 3
- Day381:说一下 JavaScript 严格模式下有哪些不同?
- Day382:说一下 setTimeout 和 setInterval 的区别,包含内存方面的分析?
- Day383:说下 React 的 useEffect、useCallback、useMemo HOT 2
- Day384:JavaScript 中如何实现一个类?怎么实例化这个类? HOT 2
- Day385:在一个 DOM 上同时绑定两个点击事件:一个用捕获,一个用冒泡。事件会执行几次?先执行冒泡还是捕获? HOT 9
- Day386:写一个通用的事件侦听器函数 HOT 3
- 定时函数 HOT 1
- 小程序不维护了吗? HOT 10
- --
- 小程序里面的内容还有其他地方能学习吗
- 求小程序哇!!不然学习效率太低了 HOT 1
- 现在还能在哪里看题目答案吗?小程序关闭了😭😭 HOT 1
- #### 1)为什么会有Event Loop
- > > > @Genzhen 请教一下大佬,如果在render里面结构赋值也会影响性能吗?比如 const { page, size } = this.state这种的? HOT 1
- 考察原型链
- issue路径错误,提不了pr,可见下图
- vue中&nextTick的原理
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from fe-interview.