我正在做一个在线课程:
编写一个方法,该方法接受一个字符串并返回
true
如果字母"z"
出现在"a"
后的三个字母内。您可以假定字符串仅包含小写字母。
这是给出的解决方案:
def nearby_az(string)
i = 0
while i < string.length
if string[i] != "a"
i += 1
next
end
j = i + 1
while (j < string.length) && (j <= i + 3)
if string[j] == "z"
return true
end
j += 1
end
i += 1
end
return false
end
这个解决方案对我来说似乎不必要地复杂。具体来说,我不明白为什么需要next
。我想知道是否有人可以帮助我理解此功能。
似乎也适用于我尝试过的测试,但我想知道另一个解决方案是否更好,以及我的解决方案是否有我还没有遇到的问题。
def nearby_az(string)
i = 0
while i < string.length
while string[i] != "a"
i += 1
end
if string[i + 1] == "z" || string[i + 2] == "z" || string[i + 3] == "z"
return true
else
i += 1
end
return false
end
end
在原始答案中,如果删除next
,即使不是,i
索引也会被假定为代表"a"
位置,并且会返回错误的结果。
当您将像 "b"
这样的字符串传递给您的代码时,它将进入无限循环,因为外部条件while i < string.length
无法控制:
while string[i] != "a"
i += 1
end
请注意,一旦i
超出字符串的最后一个位置,条件string[i]
变为nil
,并且从那里开始string[i] != "a"
将得到满足。
如果字符串看起来像这样,您的解决方案将不起作用 "bbbb..."或者像这个"ABB"——那是——1)如果字符串长度<4(无字符串[i+3]),你的代码将崩溃2)如果字符串中没有"a",您的代码将崩溃。在这里,"下一个"派上了用场:"next"的目的是跳过循环的其余部分并直接跳回到它的开始。因此,原始解决方案将首先遍历字符,直到找到"a"(跳过循环的另一部分不是),并且仅当它找到"a"时 - 它才会找到"z"。
因此,正如 sawa 所说,您的循环不接受没有 a 的字符串。它也不理解带有多个 a 的字符串。例如,aaaaaaaz 将返回 false,因为它找到第一个 a,检查接下来的 3 个没有找到 z 并纾困。
您可以通过从末尾删除返回 false 并将与外部循环相同的长度条件添加到内部循环来解决问题。
他对 next 的使用等同于上述。 这是一种将两件事串在一起的方式。不过,我同意,这是不必要的复杂。
一种更简单的方法(假设你不想使用正则表达式)是只跟踪最后一次出现的"a"。
def nearby_az(string)
last_a = -4
string.chars.each_with_index do |c, i|
last_a = i if c == 'a'
return true if c == 'z' and i - last_a <= 3
end
return false
end