首页
题库
面试
求职
学习
竞赛
More+
所有博客
搜索面经/职位/试题/公司
搜索
我要招人
去企业版
登录 / 注册
首页
>
试题广场
>
直接插入排序的平均时间复杂度为( )。
[单选题]
直接插入排序的平均时间复杂度为()。
O(logn)
O(n)
O(nlogn)
O(n²)
查看正确选项
添加笔记
求解答(0)
邀请回答
收藏(38)
分享
纠错
4个回答
添加回答
5
程序猿Go师傅
编辑于 2019-10-21 21:30:49
回复(0)
4
冲鸭!冲鸭!冲鸭!
一、时间复杂度:
(1)定义:
时间复杂度是用来定性描述算法执行所需要的时间。现假设问题规模为n,解决该问题的算法中
基本操作
重复执行的次数是T(n)。如果有一个辅助函数f(n)使得T(n)/f(n)的极限值为不等于零的常数,则称f(n)是T(n)的同数量级函数,因此有T(n)=O(f(n)),此时O(f(n))称为算法的渐进时间复杂度,简称时间复杂度。时间复杂度越高,算法的执行效率越低。
(2)计算方法:
1)首先找出算法中所有重复执行的基本操作并确定总的的执行次数T(n);
2)然后找出T(n)的同数量级函数f(n);
3)最后时间复杂度是O(
f(n)
)。
技巧:
1)一重循环的时间复杂度为O(n),两重循环的时间复杂度为O(n^2),三重循环的时间复杂度为O(n^3),依次类推;
2)二分的时间复杂度为O(logn);
3)一个循环里套一个二分的时间复杂度为O(nlogn)。
(3)举例说明:
for (i = 1; i <= n; i++)
{
for(j = 1;j <= n;j++)
{
printf(“%d,%d”,i,j);
for (k =1;k <= n; k++)
{
printf(“%d,%d,%d”,i,j,k);
}
}
}
1)
第一个重复执行的基本操作printf(“%d,%d”,i,j),它的执行次数是n^2;
第二个重复执行的基本操作
printf(“%d,%d,%d”,i,j,k),它的执行次数是n^3;
总的执行次数是T(n) = n^2 + n^3。
2)
T(n)的同数量级函数是n^3。
3)
时间复杂度是O(n^3)
(4)影响算法时间复杂度的因素:
1)算法本身
2)问题规模
3)数据的初始状态
二、排序算法:
1、冒泡排序。
(1)思想:
比如现在有n个数据,要求从小到大排列。做法是:需要进行n-1轮排序,第i轮排序中将从第0个元素到第n-i-1个元素进行两两比较将该轮排序中的最大值一步一步移动都最后的位置。
(2)代码:
def bubbleSort(L):
for i in range(len(L)-1):
for j in range(0,len(L)-i-1):
if L[j] > L[j+1]:
L[j],L[j+1] = L[j+1],L[j]
优化代码:如果某一轮中来没有任何元素进行交换,说明已经都排好序了,不需要再进行下一轮排序,算法应该结束。此时可以使用一个标志来
记录控制。
def bubbleSort_new(L):
flag = False # 控制标志
for i in range(len(L)-1):
for j in range(0,len(L)-1-i):
if L[j] > L[j+1]:
L[j],L[j+1] = L[j+1],L[j]
flag = True
if not flag:
break
(3)时间复杂度:
1)最好:如果n个数据已经是排好序的,那么就是最好的情况。此时算法需要进行第一轮排序得知数据是排好序的,那么算法中基本操作if比较语句需要执行n-1次,则时间复杂度为O(n)。
2)最坏:如果n个数据正好是反序的,那么就是最坏的情况。此时算法需要进行n-1轮排序,第i轮排序需要比较n-i-1次,那么算法中基本操作if比较语句需要执行的总的次数T(n) = n-1+n-2+n-3+n-4+...+1 = n(n-1)/2,则时间复杂度为O(n^2)。
3)平均:平均执行的次数 = n-1 +
n(n-1
)/2 = 1/2n^2 + 1/2n -1,则平均时间复杂度为O(n^2)。
(4)稳定性:
序列中两个相等的元素在排序之后,它们的相对位置不会发生改变。因此冒泡排序算法是稳定的算法。
2、选择排序。
(1)思想:
比如现在有n个数据,要求从小到大排列。做法是:需要进行n-1轮排序,第i轮排序中将第i个元素与剩下的所有元素进行比较一步一步选出该轮排序中最小的元素并放在序列的最左边。
(2)代码:
def selectSort(L):
for i in range(len(L)-1):
for j in range(i+1,len(L)):
if L[j] < L[i]:
L[i],L[j] = L[j],L[i]
(3)时间复杂度:
1)最好:如果n个数据已经是排好序的,那么就是最好的情况。但与冒泡排序不同的是,它不可以设置标志提早结束循环。两层循环都必须要执行完整。所以时间复杂度为O(n^2)。
2)最坏:如果n个数据正好是反序的,那么就是最坏的情况。此时算法需要进行n-1轮排序,第i轮排序需要比较n-i-1次,那么算法中基本操作if比较语句需要执行的总的次数T(n) = n-1+n-2+n-3+n-4+...+1 = n(n-1)/2,则时间复杂度为O(n^2)。
3)平均:平均执行的次数 = n-1 + n(n-1)/2 = 1/2n^2 + 1/2n -1,则平均时间复杂度为O(n^2)。
(4)稳定性:序列中两个相等的元素在排序之后,它们的相对位置可能会发生改变。因此快速排序算法是不稳定的算法。
3、插入排序。
(1)思想:
边插入边排序。
1)先假定序列中第0个元素是有序的,
2)从序列中第1个元素开始遍历,将遍历取出的元素与其前面已经排好序的元素进行比较将其插入到有序序列中的合适位置。
(2)代码:
def insertSort(L):
for i in range(1,len(L)):
x = L[i] #待排数据
j = i -1 #从待排数据的前一个数据开始进行比较
while j >=0:
if L[j] > x:
L[j+1] = L[j]
j -= 1
L[j+1] = x
(3)时间复杂度:
1)最好:如果序列已经是排好序的,那么就是最好的情况。
此时外层循环执行n-1次,每次中内循环体执行1次,赋值语句执行一次,则T(n) = n-1,所以时间复杂度为O(n)。
2)最坏:如果序列正好是逆序的,那么就是最坏的情况。
此时外层循环执行n-1次,对应的内循环体分别执行n-(n-1),n-(n-2),n-(n-3)...,n-3,n-2,n-1,T(n)= n(n-1)/2,所以时间复杂度为O(n)。
3)平均: 平均执行的次数 = n-1 + n(n-1)/2 = 1/2n^2 + 1/2n -1,则平均时间复杂度为O(n^2)。
(4)稳定性:序列中两个相等的元素在排序之后,它们的相对位置不会发生改变。因此插入排序算法是稳定的算法。
4、快速排序。
(1)思想:
快速排序法的精髓就是利用了分治的思想。将一个规模为n的问题分解为若干个规模较小的子问题,这些子问题互相独立且与原问题形式相同;递归地解这些子问题;最后将各个子问题的解合并得到原问题的解。那么对于快速排序法来说,
1)先从序列中挑出第一个元素作为后期比较的基准。
2)将所有比基准小的元素摆放在基准的左边,所有比基准大的元素摆放在基准的右边,所有和基准相同的元素摆放在基准的任一边。在这个分区结束之后,该基准就处于序列的中间位置。
3)递归地把左分区的元素和右分区的元素再进行排序。
(2)代码:
def quickSort(L,i,j):
if i<j:
k = partion(L,i,j)#第一趟排序
quickSort(L,i,k-1)
quickSort(L,k+1,j)
def partion(L,i,j):
#先从j开始向左走直到找到一个比基准(L[i])小的数执行L[j]与L[i]交换,i += 1,然后停下来
#再从i开始向右走直到找到一个比基准(L[j])大的数执行L[i]与L[j]交换,j += 1,然后停下来
#重复上面两个步骤直到i==j
while True:
while j>i:
if L[j] >= L[i]:
j -= 1
else:
L[j],L[i] = L[i],L[j]
i += 1
break
while i < j:
if L[i] <= L[j]:
i += 1
else:
L[i],L[j] = L[j],L[i]
j -= 1
break
if i == j:
break
return i
(3)时间复杂度:
已知快速排序法的递推关系:T(n)= T(i)+T(n-i-1)+c*n
1)最好:如果每次分割,分得的两个子问题的规模是近似相等的,那么就是最好的情况。
为便于分析,假设两个子区间的元素个数恰好各为原序列个数的一半大小,估计虽然过高,但不影响大O的答案。
此时可使用递推公式T(n) = 2T(n/2)+c*n进行分析。
T(
n
)
= 2T
(n/2
)+
c
*n
T(n)= 2(
2T
(n/4
)+
c
*n
/2
)+c*n = 4T(n/4)+c*2n
T(n)=
4(
2T
(n/8
)+
c
*n/4
)+c*2n = 8T(n/8)+c*3n
...
T(n)=
nT(1)+c*logn*n = n + cnlogn
所以时间复杂度为O(nlogn)
2)最坏:如果每次分割,分得的两个子问题的规模相差很大其中一个为0,那么就是最坏的情况。
此时可使用递推公式T(n)= T(n-1)+c*n进行分析。
T(n)= T(n-1)+c*n
T(n)= T(n-2)+c*(n-1)
+c*n
T(n)= T(n-3)+c*(n-2)
+c*(n-1)
+c*n
...
T(n)= T(n-(n-1)) + c*(n-(n-2))+
c*(n-(n-3))
+...+c*(n-2)
+c*(n-1)
+c*n
=T(1)+c*2 + c*3 + ...+
c*(n-2)
+c*(n-1)
+c*n
=1 + c*(2+3+4+...+n)
=1+c*(n+2)(n-1)/2
=c/2*(n^2+n-2)+1
所以时间复杂度为O(n^2)
3)平均:分得的两个子区间内的元素个数都有可能是0,1,2,...,n-1,因此是每种情况的概率是1/n。
此时可使用递推公式T(n) = [1/nT(0)+1/nT(1)+...1/nT(n-1)] +
[1/nT(0)+1/nT(1)+...1/nT(n-1)] + cn进行分析。
T(n) = [1/nT(0)+1/nT(1)+...1/nT(n-1)] +
[1/nT(0)+1/nT(1)+...1/nT(n-1)] + cn
(4)稳定性:序列中两个相等的元素在排序之后,它们的相对位置可能会发生改变。因此快速排序算法是不稳定的算法。
发表于 2019-07-31 18:01:16
回复(0)
0
sunlight_run
最好是O(N),最坏是O(N^2)吧
发表于 2017-07-08 19:32:51
回复(0)
0
紫旋
D答案是,O(N的平方)吧
发表于 2017-05-07 09:57:43
回复(0)
这道题你会答吗?花几分钟告诉大家答案吧!
提交观点
问题信息
复杂度
排序
上传者:
阿奻_
难度:
4条回答
38收藏
11074浏览
热门推荐
相关试题
在下列表述中,错误的是()
字符串
树
排序
评论
(43)
下面关于 Spring Cloud...
Spring
评论
(1)
下面代码的输出结果 public ...
Java
评论
(1)
下列哪个选项可以用于在Java中将...
Java
评论
(1)
子曰:“名不正,则言不顺;言不顺,...
判断推理
评论
(0)
扫描二维码,关注牛客网
意见反馈
下载牛客APP,随时随地刷题