无法绕过涉及简单的for循环的基本算法吗?

时间:2019-05-15 21:14:48

标签: javascript arrays string algorithm for-loop

请考虑一个字符串,其首字母始终为"M",而其其他字符几乎可以是"I"s"U"s的任何组合(不允许其他字母,仅IsUs)。例如:MIUMUIMIUIUMUIIUIUMUIIIUIIIUIIIMIUUIUIIIUUI都是这种字符串。

我想要一个函数,该函数以任何这样的字符串作为输入,返回一个数组,该数组以所有可能的方式将模式"III"替换为"U"(如果它出现在输入字符串中)在输入中。例如,在"III"中有"U"可用"MIIII"替换的两种方式,即MUIMIU。因此,在给定MIIII作为输入的情况下,该函数应返回[MUI, MIU]

这是我的(有缺陷的)功能。其背后的思想是循环搜索输入字符串(即MIstring)以寻找"III"。每次找到"III"时,都会将MIstring添加到IIIoptions数组中,但是用"U"替换"III"

function ruleThree() {
    var IIIoptions = [];
    for (var i = 0; i < MIstring.length; i++) {
        if (MIstring.slice(i, i+3) === "III") {          
           IIIoptions.push(MIstring.replace(MIstring.slice(i, i+3), "U"));
        }
    }
    return IIIoptions;
}

鉴于输入MIIII,我希望函数返回[MUI, MIU]。但是,它返回[MUI, MUI]。我尝试使用不同的输入,它显示了相同的问题,即数组中的所有项目都相同。例如,给定字符串MIIIIUIIIIU,它会给我[MUIUIIIIU, MUIUIIIIU, MUIUIIIIU, MUIUIIIIU]而不是[MUIUIIIIU, MIUUIIIIU, MIIIIUUIU, MIIIIUIUU]。因此,该函数可以正确获取MIstring中包含的"III"s的数量,但不会返回我希望它返回的数组。

我的功能出了什么问题?

1 个答案:

答案 0 :(得分:2)

主要问题是您正在使用String.replace(),并且该方法将始终以调用方式III替换U的第一个匹配序列。找到匹配项后,您可以使用String.slice()生成带有替换内容的新字符串,如下所示:

const input = "MIIIII";

function ruleThree(str)
{
    var IIIoptions = [];

    for (var i = 0; i < str.length; i++)
    {
        if (str.slice(i, i + 3) === "III")
           IIIoptions.push(str.slice(0, i) + "U" + str.slice(i + 3));
    }
    
    return IIIoptions;
}

console.log(ruleThree(input));
.as-console {background-color:black !important; color:lime;}
.as-console-wrapper {max-height:100% !important; top:0;}

但是,请注意,如果一次需要多个替换,则前一种方法将失败,例如,如果您的输入为MIIIIII,则不会生成MUU字符串。在这种情况下,您将必须使用递归方法:

const input = "MIIIIIII";

function getCombs(str, res = new Set())
{
    for (var i = 0; i < str.length; i++)
    {
        if (str.slice(i, i + 3) === "III")
        {
           let r = str.slice(0, i) + "U" + str.slice(i + 3);
           res.add(r);
           getCombs(r, res);
        }
    }

    return [...res];
}

console.log(getCombs(input));
.as-console {background-color:black !important; color:lime;}
.as-console-wrapper {max-height:100% !important; top:0;}