Javascript 我可以在递归问题中使用其他参数吗?

Javascript 我可以在递归问题中使用其他参数吗?,javascript,recursion,Javascript,Recursion,我在一家公司接受面试,面试官问了我一个递归问题。这是一次在线采访,因此,他在CodeSandbox(在线代码编辑器/协作工具)上设置了问题陈述和函数签名。我应该把身体填满。他在函数签名中只有一个参数。我添加了另一个参数只是为了跟踪结果。他说我不应该添加另一个参数(我为附加参数提供了一个默认值),因为它会更改函数签名 现在,在我看来,如果你在签名中添加一个可选的参数,这不会有任何区别。让我举一个简单的例子让大家更清楚地了解: 问题:检查输入是否为回文 解决方案1: function isPalin

我在一家公司接受面试,面试官问了我一个递归问题。这是一次在线采访,因此,他在CodeSandbox(在线代码编辑器/协作工具)上设置了问题陈述和函数签名。我应该把身体填满。他在函数签名中只有一个参数。我添加了另一个参数只是为了跟踪结果。他说我不应该添加另一个参数(我为附加参数提供了一个默认值),因为它会更改函数签名

现在,在我看来,如果你在签名中添加一个可选的参数,这不会有任何区别。让我举一个简单的例子让大家更清楚地了解:

问题:检查输入是否为回文

解决方案1:

function isPalindrome(input, index = 0){
    const isAMatch = input[index] === input[input.length - 1 - index]

    if (index === Math.floor((input.length - 1) / 2)) {
        return isAMatch
    }

    if (isAMatch) {
        return isPalindrome(input, ++index)
    }

    return isAMatch
}
在上面的解决方案中,我添加了一个可选参数:
index
,以跟踪要匹配的索引。这里的问题是,添加此可选参数是否合理

解决方案2:

函数isAlindrome(str){
if(str.length==1)返回true;
if(str.length==2)返回str[0]==str[1];
if(str[0]==str.slice(-1))返回isAlindrome(str.slice(1,-1))
返回false;
}
在这个解决方案中,我们不使用任何额外的参数


现在我再次重复这个问题,解决方案1会被认为是无效的解决方案吗?

如果你想在这个问题上获得满分,请使用具有你想要的任何参数的助手方法


通常,像这样的面试问题反映了实际工作,因为专业开发人员花费大量时间实现他们无法控制的接口。专家可以在不改变公共接口的情况下,通过使用额外的方法或类实现他们所需要的任何东西来处理这些限制。提问者想知道你是否是那种专家。

如果语言允许你这样做,那就没什么错。 只是面试官想让你考虑第二个解决方案

溶液1和溶液no2一样正确

在某些情况下,我们必须传递一些附加参数来区分这是主条目还是递归条目

长话短说,你的两个答案都同样正确。

解决方案1是正确的

function isPalindrome(input){
let index = [...arguments][1] || 0; // this part is changed
print(index)
const isAMatch = input[index] === input[input.length - 1 - index]

if (index === Math.floor((input.length - 1) / 2)) {
    return isAMatch
}

if (isAMatch) {
    return isPalindrome(input, ++index)
}

return isAMatch;
但是,你可以试试

功能反向限制(str){
如果(str.length==1){
返回str;
}
返回反向限制(str.slice(1))+str[0];
}
函数isAlindrome(str){
返回str==反向限制(str);
};

console.log(isPalindrome('12345678987654321'))
我同意两个答案都是正确的,作为面试官,我将为您提供全部学分

但是如果你不想做数组.SLICE(),仍然继续使用第一个解决方案,我认为这是非常干净的,那么我宁愿考虑这个技巧来满足面试官的要求。但同样,你的答案是绝对正确的

function isPalindrome(input){
let index = [...arguments][1] || 0; // this part is changed
print(index)
const isAMatch = input[index] === input[input.length - 1 - index]

if (index === Math.floor((input.length - 1) / 2)) {
    return isAMatch
}

if (isAMatch) {
    return isPalindrome(input, ++index)
}

return isAMatch;

}

面试官可能会认为,来电者可以用无效数据操纵你的方法。范例

isPalindrome("welcome", 2) 

争论的焦点是用户选择他们有传递任何值的完全自由。但是,如果您是解决方案提供商,则应该验证输入。将所有输入视为邪恶。

每当向签名添加默认参数时,可能存在一个缺陷。正如其他人所指出的,用户可以用他们选择的任何值来调用它

使用解决方案1,调用

<代码>isPalindrome('堤坝',1) 将产生
true
,因为您忽略了第一个和最后一个字母

更糟糕的是

isPalindrome('madam',4)
将重复出现,直到堆栈空间用完,调用
isPalindrome('madam',5)
,这将调用
isPalindrome('madam',6)
,等等

虽然您可以将其记录下来,以确保用户不会以愚蠢的方式执行此操作,但很可能他们甚至不知道自己正在执行此操作

['kayak','level','leve','non-alindrome','madam']
//=>[对,对,错,错,对]
正如所料

通常当我们有
[…].map(x=>foo(x))
时,我们可以简单地用
[…].map(foo)
替换它。这是清理代码的好方法

但在这里:

['kayak'、'level'、'leve'、'non-alindrome'、'madam']地图(isalindrome)
将引发该异常,因为
map
为提供给它的函数、索引和原始数组提供了额外的参数。这就要求

isPalindrome('kayak',0)
isPalindrome('级别',1)
isPalindrome(“堤坝”,2)
isPalindrome(“非Alindrome”,3)
isPalindrome('女士',4)
它会把“堤坝”弄错,然后在“夫人”上爆炸

关键是我们经常使用
map
,就好像它只提供我们关心的项目一样。JS允许这样做,它非常有用。但是,如果我们的函数使用额外的参数做一些事情,我们可能会被它咬到

有多种方法可以解决这个问题。当然,最简单的方法就是忽略它。警告买主。但你永远不知道什么时候它会回来咬你。如果这是一个内部函数,不打算被任何其他人使用,这可能是好的。但作为其他人使用的函数,这可能是一个问题

第二种技术是简单地添加包装器函数。您的递归函数及其辅助变量将成为一个内部函数,不会公开给外界,您可以编写一个包装器函数,以您选择的方式调用它。然后,您可以将这些帮助程序设置为默认值,或者从包装器中传递它们。因此

函数\u isAlindrome(输入,索引){
//…这里是递归实现
}
函数isAlindrome(输入){
返回\u isAlindrome(输入,0)
}
这是这个问题的一般解决办法。我将其用于需要辅助变量的公共递归函数。对于内部的,我经常写为y