O(n ^ 2)比O(n)快吗?

时间:2018-11-19 18:38:23

标签: c# .net big-o

我编写了一个小程序来测试我创建的两个独立扩展方法的速度,详细信息在以下屏幕截图中:

public static class Extensions
{
    public static List<string> ParseEmails(this string[] emails, char[] charsToSplitOn)
    {
        List<string> list = new List<string>();
        foreach (string email in emails)
        {
            string[] splitArr = email.Replace(" ", "").Split(charsToSplitOn, StringSplitOptions.RemoveEmptyEntries);
            foreach (string item in splitArr)
            {
                list.Add(item);
            }
        }
        return list;
    }

    public static string[] ParseEmails2(this string[] emails, char[] charsToSplitOn)
    {
        string str = string.Empty;
        foreach (string item in emails)
        {
            str += item + ';';
        }
        return str.Replace(" ", "").Split(charsToSplitOn, StringSplitOptions.RemoveEmptyEntries);
    }
}

enter image description here

Main方法初始化一个Stopwatch类,以跟踪每种方法执行iterations次的时间。

第一种方法ParseEmails在另一个for循环中有一个for循环,而第二种方法'ParseEmails2'只有一个for循环。

我希望第二种方法ParseEmails2会更快,因为据我了解,这是在O(n)时间内完成的,而我的第一种方法ParseEmails是在O(n ^ 2)时间内完成。

如果这是真的,那么我的结果难道不应该指出ParseEmails2是这两种方法中的更快者吗?

4 个答案:

答案 0 :(得分:0)

您必须准确了解O(n^2)的含义。什么是n?如果n对应于电子邮件的数量(在emails数组中),则第一种方法的运行规模为O(n),因为您对所有电子邮件进行了一次迭代。

在第二种方法中,您使用字符串连接,这意味着在每次循环运行时都要创建一个新的字符串,导致复杂度为O(n^2)

更喜欢使用StringBuilder或在循环内串联字符串的列表。

答案 1 :(得分:0)

好吧...您似乎不了解O标记的目的,O很少涉及性能,而更多地涉及性能的一致性。 O(n²)的意思是抛物线,O(n)的意思是直线,但是它没有告诉您实际时间。因此,一旦涉及到许多元素,O(n)算法就应该更快。原因可能是您使用string的{​​{1}}和+=运算符,它们使用C#+的{​​{1}}语义。

答案 2 :(得分:-1)

ParseEmails2实际上不是O(n),因为

str += item + ';';

包含一个循环。

答案 3 :(得分:-1)

您应该检查此链接。 字符串串联与构建器性能 String concatenation vs String Builder. Performance

在这种情况下,字符串生成器可能会稍微快一些,但实际上可能不足以使它烦恼。重新创建字符串的次数(因为字符串是不可变的,并且连接会强制从现有的两个字符串中创建一个新字符串)。

因为在非常一步上分配内存会导致更多时间。