Python 如何准确识别O(nlogn)?

Python 如何准确识别O(nlogn)?,python,python-3.x,algorithm,time-complexity,big-o,Python,Python 3.x,Algorithm,Time Complexity,Big O,我从某种意义上理解了O(logn),它增长很快,但随着输入的增加,增长速度会减慢。 我不能完全理解 O(非登录) 复杂度为nlogn和复杂度为n+logn的算法之间的差异 我可以使用电话簿示例的修改和/或一些基本python代码来理解这两个查询您如何看待O(n^2)? 就个人而言,我喜欢把它看作是做O(n)工作O(n)次 设计的O(n^2)算法是迭代0,1,…,n-1中的所有数字对 def print_pairs(n): for i in range(n): for j

我从某种意义上理解了O(logn),它增长很快,但随着输入的增加,增长速度会减慢。 我不能完全理解

  • O(非登录)

  • 复杂度为nlogn和复杂度为n+logn的算法之间的差异


  • 我可以使用电话簿示例的修改和/或一些基本python代码来理解这两个查询

    您如何看待
    O(n^2)
    ? 就个人而言,我喜欢把它看作是做
    O(n)
    工作
    O(n)

    设计的
    O(n^2)
    算法是迭代
    0,1,…,n-1中的所有数字对

    def print_pairs(n):
        for i in range(n):
            for j in range(i + 1, n):
                print('({},{})'.format(i, j))
    
    使用与上面类似的逻辑,您可以执行
    O(logn)
    工作
    O(n)
    次,并且时间复杂度为
    O(nlogn)

    例如,我们将使用二进制搜索来查找数组中元素的所有索引

    是的,我知道这是一个愚蠢的例子,但在这里我不想关注算法的有用性,而是复杂性。为了保证算法的正确性,我们假设输入数组已排序。否则,我们的二进制搜索无法按预期工作,可能会无限期运行

    def find_indices(arr):
        indices = []
        for num in arr:
            index = binary_search(arr, 0, len(arr), num)
            indices.append(index)
        return indices
    
    def binary_search(arr, l, r, x): 
    
        # Check base case 
        if r >= l: 
    
            mid = l + (r - l)/2
    
            # If element is present at the middle itself 
            if arr[mid] == x: 
                return mid 
    
            # If element is smaller than mid, then it  
            # can only be present in left subarray 
            elif arr[mid] > x: 
                return binary_search(arr, l, mid-1, x) 
    
            # Else the element can only be present  
            # in right subarray 
            else: 
                return binary_search(arr, mid + 1, r, x) 
    
        else: 
            # Element is not present in the array 
            return -1
    
    关于你的第二个问题,
    当然,
    logn有一本很棒的书,用一种非常简单的语言详尽地解释了算法复杂性检测(除其他外)。
    logn
    是一个比
    n
    慢得多的函数。当计算机科学家谈到big-O时,他们对超大输入值函数的增长感兴趣。函数在某个小数值或拐点附近所做的是无关紧要的

    许多常用算法的时间复杂度为
    nlogn
    。例如,当输入数据一分为二时,需要执行
    n
    步骤
    log_2(n)
    次。在研究该算法之后,直觉可能会发现它的复杂性是
    n logn
    ,但通过研究描述(递归)算法的递归关系,你可以得出相同的结论——在这种情况下
    T(n)=2*T(n/2)+n
    。更一般但可能最不直观的是,可以应用。简言之,如果某些算法有特定的运行时间这一点不明显,不要感到害怕——有很多方法可以用来进行分析

    关于“复杂度n+logn”,这不是big-O符号的使用方式。你可能有一个算法可以
    n+logn
    工作,但是我们不把它叫做
    O(n+logn)
    ,而是把它叫做
    O(n)
    ,因为
    n
    logn
    增长得快得多,以至于
    logn
    这个术语可以忽略不计。其要点是只说明增长最快的期限的增长率


    n log n
    相比,
    log n
    更快。如果
    logn
    是将项目插入自平衡搜索树的时间复杂度,
    nlogn
    将是将
    n
    项目插入此类结构的复杂度。

    技术上,复杂度为O(n+logn)和复杂度为O(n)的算法是相同的,当n增长时,对数n项变得可以忽略

    O(n)呈线性增长。坡度是恒定的


    O(n logn)呈超线性增长。斜率(缓慢)增加。

    阅读任何算法书中关于复杂性的章节,这是一个很好的答案。我想补充一点,大O表示法将
    logn
    更多地定义为
    常量
    之间的附加级别,例如1和
    n
    。这实际上并不一定要精确到
    logn
    (尽管它通常是这样的,只要n足够大)。如果您有两个循环,外部循环在
    n
    上迭代,而内部循环从小开始变大(或者反过来),或者它有一些巧妙的元素跳过策略,那么您很可能有一个
    n长的n
    案例