【发布时间】:2018-05-12 05:55:51
【问题描述】:
在一次采访中,有人问我以下算法的时间复杂度:
static bool SetContainsString(string searchString, HashSet<string> setOfStrings)
{
for (int i = 0; i < searchString.Length; i++)
{
var segment = searchString.Substring(0, i + 1);
if (setOfStrings.Contains(segment))
{
var remainingSegment = searchString.Substring(segment.Length);
if (remainingSegment == "") return true;
return SetContainsString(remainingSegment, setOfStrings);
}
}
return false;
}
我回答“线性”是因为在我看来它只循环通过 searchString 的长度。是的,它是递归的,但是递归调用只是在字符串中还没有被迭代的部分上,所以最终的结果迭代次数就是字符串的长度。
我的面试官告诉我,最坏情况下的时间复杂度是指数级的。
谁能帮我澄清一下?如果我错了,我需要了解原因。
【问题讨论】:
-
"但是递归调用只在字符串中还没有被迭代过的部分,所以迭代的最终结果数就是字符串的长度" - 你如何证明这一步?
-
看起来像“三角形 n”。一个长度为 5 的字符串看起来会循环 15 次。 6 会循环 20 次。似乎不是指数的。
-
你确定面试中的代码有一个无条件的
return SetContainsString(remainingSegment, setOfStrings);,而不是只有在递归调用返回true时才返回那个结果? -
@user2357112 我开始知道我哪里出了问题。谢谢!在根情况下,它仍然会遍历字符串的所有元素,即使递归调用仅遍历一个子集——当进行递归调用时,没有什么可以打破根循环。所以我们在根案例中有 N,第一个递归中有 N-1,下一个递归有 N-2,等等。
-
该函数似乎很可能是为了检查
searchString是否是setOfStrings中的字符串连接(允许重复),在这种情况下,无条件的return SetContainsString(remainingSegment, setOfStrings);应该是@ 987654327@,并且该函数将具有指数运行时间。
标签: string algorithm time-complexity big-o