原題鏈接
https://leetcode.cn/problems/generate-fibonacci-sequence/
題目分析:
該題目要求我們實現(xiàn)一個生成器函數(shù)狗准,用于產(chǎn)生斐波那契數(shù)列。斐波那契數(shù)列是一個由0和1開始茵肃,后續(xù)每個數(shù)字都是前兩個數(shù)字之和的數(shù)列腔长。題目給出的遞推公式為 Xn = Xn-1 + Xn-2。
解題思路:
這個問題可以使用生成器函數(shù)的特性來解決验残。我們創(chuàng)建一個生成器函數(shù)捞附,使用yield
關(guān)鍵字在每次迭代中產(chǎn)生下一個斐波那契數(shù)。這個問題可以有兩種解法您没,下面我們將分別介紹并解析這兩種解法鸟召。
解法一:
var fibGenerator = function*() {
let prev = 0
let curr = 1
while (true) {
yield prev;
[prev, curr] = [curr, prev + curr]
}
};
在這個解法中,我們首先初始化了兩個變量prev
和curr
氨鹏,分別表示當(dāng)前的斐波那契數(shù)和下一個斐波那契數(shù)欧募。在每次迭代中,我們首先通過yield
關(guān)鍵字產(chǎn)生當(dāng)前的斐波那契數(shù)仆抵,然后更新prev
和curr
以準(zhǔn)備產(chǎn)生下一個斐波那契數(shù)跟继。
這里需要注意的是,由于yield
會暫停函數(shù)的執(zhí)行镣丑,因此[prev, curr] = [curr, prev + curr]
這一行代碼實際上是在yield
暫停后舔糖,也就是在下一次迭代開始時執(zhí)行的。這就保證了在每次迭代中莺匠,我們都能準(zhǔn)確地產(chǎn)生出斐波那契數(shù)列中的下一個數(shù)字金吗。
解法二:
var fibGenerator = function* (prev = 0, curr = 1) {
yield prev;
return yield* fibGenerator(curr, prev + curr);
};
在這個解法中,我們使用了yield*
表達式趣竣,用于在當(dāng)前生成器函數(shù)中產(chǎn)生另一個生成器函數(shù)的所有值辽聊。在每次迭代中,我們首先產(chǎn)生當(dāng)前的斐波那契數(shù)期贫,然后通過yield*
關(guān)鍵字調(diào)用新的斐波那契生成器函數(shù),以產(chǎn)生下一個斐波那契數(shù)异袄。
這里需要注意的是通砍,yield*
表達式實際上會產(chǎn)生被委托生成器的所有值。因此烤蜕,在yield pre
產(chǎn)生當(dāng)前斐波那契數(shù)后封孙,return yield* fibGenerator(cur, pre + cur)
就會開始產(chǎn)生下一個斐波那契生成器的所有值,也就是斐波那契數(shù)列中的下一個數(shù)字讽营。
yield*
是一個用于生成器函數(shù)中的語法虎忌,被稱為委托給另一個生成器的 yield
表達式。yield*
關(guān)鍵字可以在生成器函數(shù)內(nèi)部使用橱鹏,可以產(chǎn)生另一個可迭代對象(例如另一個生成器函數(shù)膜蠢,或者數(shù)組堪藐、字符串等)的所有值。
例如挑围,我們可以使用 yield*
來處理數(shù)組:
function* iterateArray(array) {
yield* array;
}
const arrayGen = iterateArray([1, 2, 3, 4, 5]);
console.log(arrayGen.next().value); // 1
console.log(arrayGen.next().value); // 2
或者我們也可以使用 yield*
來處理字符串:
function* iterateString(str) {
yield* str;
}
const stringGen = iterateString("Hello");
console.log(stringGen.next().value); // 'H'
console.log(stringGen.next().value); // 'e'
yield*
在生成器函數(shù)中處理可迭代對象時礁竞,可以將對象中的每一個值產(chǎn)生出來。
在解法二中杉辙,yield* fibGenerator(cur, pre + cur)
表示把生成下一個斐波那契數(shù)的任務(wù)委托給了新的 fibGenerator(cur, pre + cur)
生成器函數(shù)模捂。yield*
表達式的值為被委托的生成器最后一次 yield
的值或 return
的值。
讓我們看一個更簡單的例子來理解 yield*
的工作方式:
function* gen1() {
yield 2;
yield 3;
}
function* gen2() {
yield 1;
yield* gen1();
yield 4;
}
var g = gen2();
console.log(g.next()); // { value: 1, done: false }
console.log(g.next()); // { value: 2, done: false }
console.log(g.next()); // { value: 3, done: false }
console.log(g.next()); // { value: 4, done: false }
console.log(g.next()); // { value: undefined, done: true }
在這個例子中蜘矢,gen2
生成器函數(shù)在 yield* gen1()
時把控制權(quán)交給了 gen1
生成器函數(shù)狂男,于是 gen1
的所有值(2 和 3)都被 gen2
產(chǎn)生出來。等到 gen1
生成完所有的值之后品腹,控制權(quán)再次返回給 gen2
岖食,繼續(xù)產(chǎn)生剩下的值。
因此珍昨,yield* fibGenerator(cur, pre + cur)
就會產(chǎn)生 fibGenerator(cur, pre + cur)
這個生成器函數(shù)的所有值县耽,也就是斐波那契數(shù)列中的下一個數(shù)字。
總結(jié):
以上就是生成斐波那契數(shù)列的兩種解法及其解析镣典。在實際編程中兔毙,生成器函數(shù)和 yield
關(guān)鍵字是非常有用的工具,可以幫助我們更方便地處理序列化的數(shù)據(jù)兄春,并允許我們以需求驅(qū)動的方式來產(chǎn)生數(shù)據(jù)澎剥,而不是一次性產(chǎn)生所有數(shù)據(jù)。這種特性在處理大量數(shù)據(jù)或者需要流式處理數(shù)據(jù)的場景中特別有用赶舆。