我最近有一次面試,你必須遞回地遍歷一個字串,如果它包含一個AB|| BA|| CD|| DC,它必須從陣列中洗掉。您將遞回地檢查這一點,因為洗掉CDfromACDBB會給您 anAB然后您必須洗掉它才能將 aB作為字串回傳。
這就是我所擁有的,當我對其進行測驗時,我發現它在回圈深處提出了正確的答案,但它永遠不會回到頂部。
我錯過了什么?
const LETTERS = [/AB/g, /BA/g, /CD/g, /DC/g];
const stringGame = (string) => {
let newString = '';
if(string.length <= 1) return string;
LETTERS.forEach(regExToCheck => {
if(string.match(regExToCheck)) {
newString = string.replace(regExToCheck, '')
}
stringGame(newString);
})
return newString
}
// Expect answer: CAACC
console.log(stringGame('ABDCABCABAAABCCCD'))
uj5u.com熱心網友回復:
- 移動遞回,
return遞回,和- 添加一個必要條件來結束遞回:
const LETTERS = [/AB/g, /BA/g, /CD/g, /DC/g];
const stringGame = (string) => {
let newString = '';
if (string.length <= 1) return string;
LETTERS.forEach(regExToCheck => {
if (string.match(regExToCheck)) {
newString = string.replace(regExToCheck, '')
}
})
// Moved, returned, and ended recursion
return ('' === newString) ? string : stringGame(newString);
}
// Expect answer: CAACC
console.log(stringGame('ABDCABCABAAABCCCD'))
當遞回函式時,即在自身內部執行函式時return,需要使用該執行的 'ed 值,通常是return'ed:
return stringGame(newString);
...為了讓它恢復遞回級別。
此外,由于該replace()函式使用正則運算式全域替換標志 ( g) 所有,例如AB's,都在一次執行中被替換,因此無需在forEach()回圈內遞回:
LETTERS.forEach(regExToCheck => {
if(string.match(regExToCheck)) {
newString = string.replace(regExToCheck, '')
}
stringGame(newString); // <-- double oops
})
相反,在回圈之后return遞回,并且執行的值:
LETTERS.forEach(regExToCheck => {
if(string.match(regExToCheck)) {
newString = string.replace(regExToCheck, '')
}
})
return stringGame(newString);
遞回函式的另一個原則是提供退出策略——定義結束遞回、冒泡并回傳最終結果的條件。
提供的唯一退出條件是:
if (string.length <= 1) return string;
當然,如果只剩下一個字符,將找不到匹配項——結束遞回的適當時間。但是,更重要的是,當有多個字符但找不到匹配項時,還需要有一條退出路徑。
有多種方法可以確定這一點,但在問題中提供的情況下,最方便的是在回圈通過正則運算式/替換例程后沒有對字串進行任何更改。由于每次遞回函式都會實體化stringGame()一個空字串(newStringnewString
if ( '' === newString ) {
return string;
}
else {
return stringGame(newString);
}
...否則,遞回。
uj5u.com熱心網友回復:
該stringGame函式沒有副作用,因此此處回圈中的行:
stringGame(newString);
不做任何事情 - 您需要將遞回呼叫的結果傳達回外部級別。
解決此問題的更好方法是將 組合LETTERS成一個正則運算式,然后用空字串替換所有匹配項,直到替換不產生任何更改。
const LETTERS = [/AB/g, /BA/g, /CD/g, /DC/g];
const pattern = new RegExp(
LETTERS
.map(re => {
const str = String(re);
return str.slice(1, str.length - 2);
})
.join('|'),
);
const stringGame = (string) => {
const newString = string.replace(pattern, '');
return newString === string
? string
: stringGame(newString);
}
// Expect answer: CAACC
console.log(stringGame('ABDCABCABAAABCCCD'))
(如果要在構造模式中使用全域標志,則必須考慮.lastIndex)
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/526275.html
標籤:javascript递归
下一篇:如何從遞回函式中操作和回傳字串?
