分析运行时间,Big O.

时间:2016-11-28 17:13:59

标签: algorithm haskell time-complexity big-o

我在分析算法的时间复杂度方面遇到了问题。

例如以下Haskell代码,它将对列表进行排序。

sort xs
|isSorted xs= xs
|otherwise= sort (check xs)
    where 
    isSorted xs=all (==True) (zipWith (<=) xs ( drop 1 xs))
    check [] =[]
    check [x]=[x]
    check (x:y:xs) 
        |x<=y = x:check (y:xs)
        |otherwise=y:check (x:xs)

因此,n是列表的长度,t_isSorted(n)是运行时间函数:有一个常量t_drop(n)= c和t_all(n)= n,t_zipWith(n)= n:

   t_isSorted(n)= c + n +n

对于t_check:

   t_check(1)=c1

   t_check(n)=c2 + t_check(n-1), c2= for comparing and changing an element
          .
          .
          .
   t_check(n)=i*c2 + tcheck_(n-i), with i=n-1
            =(n-1)*c2 + t_check(1)
            =n*c2 - c2 + c1

我究竟如何将这些组合起来得到t_sort(n)?我想在最坏的情况下,排序xs必须运行n-1次。

2 个答案:

答案 0 :(得分:3)

isSorted确实是O(n),因为它由zipWith支配,而O(n)又是check,因为它对其参数进行了线性传递。

O(n)本身是O(n*log(n)),因为它每次执行只调用一次,并且它总是从列表中删除一定数量的元素。最快的排序算法(不知道关于列表的更多信息)在O(log(n!))中运行(相当于check时间)。有一个数学证明,这个算法更快,所以它不可能对整个列表进行排序。

[3,2,1]只会使事情迈出一步;它实际上是一次冒泡排序。

考虑对此列表进行排序:check [3,2,1] = 2:(check [3,1]) -- since 3 > 2 check [3,1] = 1:(check [3]) -- since 3 > 1 check [3] = [3]

[2,1,3]

将返回“已排序”列表3

然后,只要列表没有排序,我们循环。由于我们可能只将一个元素放在正确的位置(如上例中的O(n)所示),我们可能需要O(n) * O(n) = O(n^2)循环迭代。

这总计时间复杂度为{{1}}

答案 1 :(得分:1)

时间复杂度为O(n^2)

您是对的,一步需要O(n)次(对于isSortedcheck个功能)。它被称为不超过n次(甚至可能是n - 1,它对时间复杂度并不重要)(在第一次调用之后,最大元素保证是最后一个元素,第二次调用后第二大的情况也是如此。我们可以证明最后k个元素是最大的,并在k调用后正确排序。它仅交换相邻元素,因此每步最多可以移除一个反转。由于最坏情况下的反转次数为O(n^2)(即n * (n - 1) / 2),因此时间复杂度为O(n^2)