C# 如何计算该函数的时间复杂度,该函数检查字符串是否具有所有唯一字符?
《破解编码面试》一书中讨论了一个函数,该函数确定字符串是否包含所有唯一字符。本书使用位移位的答案在问题链接中(请参见页面顶部的答案),我在这里不再重复 Java的答案有一个O(N)复杂度,我无法理解O(N)的实际含义。实际上,我想知道我刚才写的这个实现的时间复杂度是多少。是O(N)吗?如何理解复杂性C# 如何计算该函数的时间复杂度,该函数检查字符串是否具有所有唯一字符?,c#,.net,C#,.net,《破解编码面试》一书中讨论了一个函数,该函数确定字符串是否包含所有唯一字符。本书使用位移位的答案在问题链接中(请参见页面顶部的答案),我在这里不再重复 Java的答案有一个O(N)复杂度,我无法理解O(N)的实际含义。实际上,我想知道我刚才写的这个实现的时间复杂度是多少。是O(N)吗?如何理解复杂性 static void Main(string[] args) { string stringToCheck ; bool hasAllUniqueChars
static void Main(string[] args)
{
string stringToCheck ;
bool hasAllUniqueChars = false;
stringToCheck = "Test";
hasAllUniqueChars = CheckForUniqueChars(stringToCheck);
Console.WriteLine("String is Unique {0}", hasAllUniqueChars);
Console.Read();
}
private static bool CheckForUniqueChars(string stringToCheck)
{
for (int i = 0; i < stringToCheck.Length - 1; i++)
{
for (int j = i; j < stringToCheck.Length - 1; j++)
{
if (Char.ToUpper(stringToCheck.ElementAt(i)) ==
Char.ToUpper(stringToCheck.ElementAt(j+1)))
{
return false;
}
}
}
return true;
}
static void Main(字符串[]args)
{
字符串检查;
bool hasaluniquechars=假;
stringToCheck=“测试”;
HASALUNIQUECHARS=检查唯一字符(stringToCheck);
WriteLine(“字符串是唯一的{0}”,hasAllUniqueChars);
Console.Read();
}
专用静态bool CheckForUniqueChars(字符串stringToCheck)
{
对于(int i=0;i
对于Test、Test、Hello,返回false;对于超人、蜘蛛侠和海绵,返回true,工作正常
谢谢你编辑:根据其他用户的建议,它是O(n^3),或者与三阶多项式成比例增长。这是因为ElementAt()在字符串中循环 这种复杂性的关键在于迭代。这一结构:
for (each item in this thing)
{
for(each item in this thing)
{
if (iterate through this thing to check a condition)
}
}
有一个与三阶多项式成比例的增长阶。这并不像其他类似的例程那样糟糕,因为通过内部循环的内部迭代随着您的增量而变小,但您仍然在对字符串的每个元素进行迭代,并对这些迭代中的每个元素在字符串上进行迭代。如果你的算法是O(n^3),你就可以重构它
如果您感兴趣的话,无ElementAt()调用,它与它的迭代方式非常相似。您的算法是O(n^2),或者更准确地说,可以是O(n^2)。可能是,因为现在是O(n^3)
ElementAt()
方法在IEnumerable
上是O(n),所以因为它在两个嵌套循环中执行,所以整个方法是O(n^3)
通过将string
s转换为char[]
before循环,并使用数组索引器而不是ElementAt
扩展方法,可以实现O(n^2):
private static bool CheckForUniqueChars(string stringToCheck)
{
var chars = stringToCheck.ToCharArray();
for (int i = 0; i < stringToCheck.Length - 1; i++)
{
for (int j = i; j < stringToCheck.Length - 1; j++)
{
if (Char.ToUpper(chars[i]) == Char.ToUpper(chars[j+1]))
{
return false;
}
}
}
return true;
}
专用静态bool CheckForUniqueChars(字符串stringToCheck)
{
var chars=stringToCheck.tocharray();
对于(int i=0;i
Bonus:另一种O(n)方法(因为HashSet
查找是O(1)):
专用静态bool CheckForUniqueChars(字符串stringToCheck)
{
var characters=新的HashSet();
foreach(stringToCheck中的变量字符)
如果(!个字符。添加(个字符))
返回false;
返回true;
}
调用符号O(N)。它提供的是算法所需的(基本)操作量相对于其输入大小的上限。输入的大小通常表示为N
如果原语操作的数量与输入大小无关,则算法的复杂度为O(1),即恒定时间
如果基元运算量随着N的增长而线性增长(即:当N翻倍时,运算量也会翻倍),则时间复杂度是线性的,即O(N)
在您的示例中,对于普通读者来说,上限似乎是O(N^2):
for (each item in input)
for (each item in input)
// do something
当N增加一倍时,运算量将增加四倍
然而,由于ElementAt的时间复杂度是线性的且不是常数,因此复杂度实际上是O(N^3)。不是O(?)
但这接近于O(N),因为对于这一点,哈希集应该接近于O(1)。注意HashSet。计数是O(1)
HashSet chars=new HashSet();
字符串password=“password”;
Int32计数=0;
炭杯;
foreach(密码中的字符c)
{
计数++;
cUpper=char.ToUpper(c);
如果(!chars.Add(char.ToUpper(c)))
{
System.Diagnostics.Debug.WriteLine(“非uniue”);
打破
}
}
if(count==chars.count)System.Diagnostics.Debug.WriteLine(“uniue”);
+我看不出Marcin有这个答案,但没有这个答案ToUpper比ToLower好用,但我忘了为什么
String具有不区分大小写的比较,但char不区分大小写(因为
String.ElementAt
在其中生成另一个循环)。在维基百科上阅读更多关于大O符号的内容:这个问题似乎离题了,因为它是关于大O的notation@MarcinJuraszek这不是另一个循环。这只是使用两个循环中的索引进行比较。@是的,但不是简单的数组查找ElementAt()
方法在IEnumerable
上是O(n),所以整个方法是O(n^3),不是吗?(ElementAt
在IList
上是O(1),但string
不实现IList
)。检查此项:ElementAt()
在内部生成另一个循环。是的,确实如此。正在修改,因为这现在是一个三阶多项式。@MarcinJuraszek该实现可以很容易地更改为O(N^2)。@Asad Yes,只需两次tocharray()
调用。然而,当前的实现是O(n^3)。@MarcinJuraszek我知道。能够
for (each item in input)
for (each item in input)
// do something
HashSet<char> chars = new HashSet<char>();
string password = "password";
Int32 count = 0;
char cUpper;
foreach (char c in password)
{
count++;
cUpper = char.ToUpper(c);
if (!chars.Add(char.ToUpper(c)))
{
System.Diagnostics.Debug.WriteLine("not uniue");
break;
}
}
if(count == chars.Count) System.Diagnostics.Debug.WriteLine("uniue");