zoukankan      html  css  js  c++  java
  • 我们为什么不能只用O记号来谈论算法?

    在刷LeetCode-1TwoSum的时候,有个人在论坛留言,大致意思如下:

    我的算法击败了90%的人,O(nlgn)算法比O(n)算法快。

    我觉得这个人是不懂算法的。让我一步一步解释。

    # O的含义

    通俗的说,O表示忽略系数的复杂度上限,常常用一个量级表示,比如n,nlgn。

    # 忽略的系数重要吗

    重要。我觉得《算法》比《算法导论》优秀的原因之一是,作者用实例证明,在不少情况下,复杂度之前的系数很重要。比如,系数可以导致O(n^2)的插入排序可以比O(nlgn)快速排序快。

    可以看一个例子。

    // 伪代码,程序1
    void add(int num)
    {
          num++;
          num++;
          num++;
          num++;
          num++;
          num++;
          num++;
          num++;
          num++;
          num++;
    }
    
    void add(int[] nums)
    {
        for (int i = 0; i < n; i++)
            add(nums[i]);
    }
    // 伪代码,程序2
    void add(int num)
    {
          num++;
    }
    
    void add(int[] nums)
    {
        for (int i = 0; i < n; i++)
            for (int j = 0; j < n; j++)
                add(nums[i]);
    }

    程序1的时间复杂度为O(n),程序2的时间复杂度为O(n^2)。如果从O来看,程序2的执行速度一定会比程序1快。

    实际上速度相当。假设nums的大小为10,程序1要执行10 * 10 = 100次i++,程序2同样执行10 * 10 * 1 = 100次i++。

    原因就在于,程序1需要的时间是10 * n,系数很大为10,而程序2需要的时间是1 * n ^ 2,系数很小为1。

    # 那个人错在哪里

    或许不是他的错,是LeetCode的错。

    渐进时间一定要在系数相对于数据量比重很小很小的时候,才有用。像排序算法一类比较简单的算法,需要上十万的数据量,才能体现出复杂度为nlgn和n^2的细小区别。

    这个人用了很聪明很简单的算法,没有用复杂的数据结构,全是基本变量,时间复杂度为O(nlgn)。而O(n)用了Hashtable,共有n个数,对于每个数,Hashtable里面有很多计算的过程,系数很大。

    此题,LeetCode可能单个数据集不是很大,系数显得格外重要。

    # 链接

    Q: https://leetcode.com/problems/two-sum/

    A: https://github.com/mofadeyunduo/LeetCode/tree/master/1TwoSum

    (请多多支持我刚刚建立的GitHub和博客,谢谢,有问题可以邮件609092186@qq.com或者留言,我尽快回复)

  • 相关阅读:
    box-shadow使用指南
    chrome的input默认样式黄色背景以及选中加粗的边框处理
    Spring AOP执行方法
    Spring JDBC主从数据库访问配置
    JS 命名冲突
    Data truncation: Truncated incorrect DOUBLE value 解决方案
    MySQL DATE_ADD() 函数
    Codeforces Round #340 (Div. 2)
    2020牛客寒假算法基础集训营3
    Codeforces Round #377 (Div. 2)
  • 原文地址:https://www.cnblogs.com/Piers/p/5747688.html
Copyright © 2011-2022 走看看