算法
1 时间复杂度

循环减半的时间复杂度是log(n)

时间复杂度是用来估计算法运行时间的一个式子(单位)。
一般来说,时间复杂度高的算法比复杂度低的算法慢。
常见的时间复杂度(按效率排序) O(1)<O(logn)<O(n)<O(nlogn)<O(n2)<O(n2logn)<O(n3)
不常见的时间复杂度(看看就好) O(n!) O(2n) O(nn) … 如何一眼判断时间复杂度? 循环减半的过程O(logn) 几次循环就是n的几次方的复杂度
算法
LOW B三人组
1.二分法查找内容 使用递归的方式来查找
li=[1,2,3,4,5,6,7,8,11,22,55,78,87,88,89,97,98,99] l2=[1,2,3,4,5] def func(num,li,start=0,end=None,): if end==None: end=len(li)-1 a=(start+end)//2 if start<=end: if li[a]<num: return func(num,li,start=a+1,end=end) elif li[a]>num: return func(num,li,start=start,end=a-1) elif li[a]==num: print(a) else: return 'meiyou ' func(55,li,start=0,)
使用循环的二分法
l=[1,2,4,5,6,8,9] def func(mun,l,start=0,end=None): if end==None: end=len(l)-1 while end>=start: mid=(start+end)//2 if mun==l[mid]: return mid elif mun>l[mid]: start=mid+1 elif mun <l[mid]: end=mid-1 else: return '么有' ret=func(11,l,start=0) print(ret)
2.斐波那契数列
# # 斐波那契数列1,2,3,5,8,13,21.....根据这样的规律, # # 编程求出400万以内最 的斐波那契数,并求出他是第 个斐波那契数。 a,b=1,2 count=2 i=0 while a+b<400000:#注意这里不能写成while i<4000000 i=a+b#因为循环结束后会包含大于400W,而是不进入下一次循环,所有写这个。 a=b b=i count+=1 print(i,count)
3.冒泡算法
时间复杂度 O(n2)
首先,列表每两个相邻的数,如果前边的比后边的大,那么交换这两个数……
如果冒泡排序中执行一趟而没有交换,则列表已经是有序状态,可以直接结束算法。 这样可以节省时间 以免都已经排序好了还要再次进行无意义的循环排序
def maopao(li): for i in range(len(li)-1): #定义一个标志位 来判断此次循环是否发生了交换,如果没有则表示排序完成 exchange=False for j in range(len(li)-1-i): if li[j]>li[j+1]: li[j],li[j+1]= li[j+1],li[j] exchange=True else: pass if not exchange: return li=[1,4,2,3,5,9,6,7,11,7] maopao(li) print(li)
4.选择排序
时间复杂度:O(n2)
li=[1,4,2,3,5,9,6,7,11,7] def select_sort(li): for i in range(len(li)-1): #从第i趟开始,无序区是li[i:] #从无序区找到最小的值,保存最小值的位置, min_loc=i #第一次默认是0 for j in range(i+1,len(li)): #因为是跟i比 所以不用再去看一下这个i 让 li[i]和 li[i] 比较大小, #所以从i+1开始 if li[j]<li[min_loc]:#这里是 如果 当前循环的值比 最小值的位置的数字小, min_loc=j #记录这个位置,替换上一次的最小值的位置的值, #当下个循环过来 就会跟这个新的位置上的数据比较大小,如果比他小的话继续替换 #直到这趟循环走完 就找到一个最小的 if min_loc!=i: #把最小的数字放在最前边,这样有序区就多了一个数据,无需去少了一个数据 li[i],li[min_loc]=li[min_loc],li[i] select_sort(li) print(li)
5.插入排序
时间复杂度:O(n2)
#关键点,要记住设置的几变量 def charupaixu(li): for i in range(1,len(li)): #这个temp存放的是当前循环的值 每次for循环存放不同的值t #用他去和他前边所有索引位置的只进行比较 #这里注意 这个temp是已经被抽取出来的数据了 所以他是悬空的 # temp的原来占的位置就空了出来,他左边的数据可以挪动过来 temp=li[i] #这个j值是一个边变化的值 是索引小于temp的所有的索引值 j=i-1 #当j 大于等于0 而且 temp 小于他位置左边的数据的值的时候 while j>=0 and temp < li[j]: # 给这个小于 li[j+1]=li[j] #每次循环都要给j 减去 1 用于从右到左依次比较,大小 j=j-1 #直到左边的数据不再小于temp的时候, 这时候这个索引位置j即是比temp大 紧挨着他的值 #所以 把拿出来的temp这张牌插入到 j+1位置上 就是 j的左边 紧挨着的位置 li[j+1]=temp charupaixu(li) print(li)

代码
#关键点,要记住设置的几变量 def charupaixu(li): for i in range(1,len(li)): #这个temp存放的是当前循环的值 每次for循环存放不同的值t #用他去和他前边所有索引位置的只进行比较 #这里注意 这个temp是已经被抽取出来的数据了 所以他是悬空的 # 他的原来占的位置就空了出来,他左边的数据可以挪动过来 temp=li[i] #这个值是一个边变化的值 是索引小于temp的所有的值 j=i-1 #当j 大于等于0 而且 temp 小于他位置左边的数据的值的时候 while j>=0 and temp < li[j]: # 给这个小于 li[j+1]=li[j] #每次循环都要给j 减去 1 用于从右到左依次比较,大小 j=j-1 #直到左边的数据不再小于temp的时候, 这时候这个索引位置j即是比temp大 紧挨着他的值 #所以 把拿出来的temp这张牌插入到 j+1位置上 就是 j的左边 紧挨着的位置 li[j+1]=temp charupaixu(li) print(li)
补充:布尔运算的短路功能
print(1>2 and 3>1) #and运算,当前边的返回值已经是false的时候就不会去看后边的结果 直接返回False了 False #or也有同理的功能
三种排序 都是时间复杂度:O(n2)
速度是 选择排序>插入排序>冒泡排序
NIU B 三人组:
1:快排 (三人组中最快的)
#此函数是对数据处理的函数 #使用当前需要排序的列表段 即是索引区间位置的这些数据 def partition(li, left, right): #找到列表区间中最左边的数据 拿出来 悬空 # 然后开始和这个区间的数据进行对比 temp = li[left] #当右索引大于左索引的时候,证明 没有找到这个 temp的中间位置 # 并把他左右分别放置比自己大小的数据 while left < right: #用于比较temp 和从最右边的数据开始 的大小 ,只要是 这个右边的数据比 temp大 #则这个右边的数据当前位置正确,右索引减一, # 再次比较 当不符合while条件之 右边比temp小的时候 while left < right and temp < li[right]: right -= 1 #把当前右边的数据拿过来放到这个temp空出来的位置 li[left] = li[right] #然后开始比较左边的数据,同理 当不符合他的条件之左边数据大于temp时 while left < right and temp > li[left]: left += 1 #把这个数据拿出来,放到刚才空出来的 right索引位置 li[right] = li[left] # 直到left=right的时候,证明找到了 这个temp的索引位置 #把temp放到这个位置上去 li[left]=temp #此时以这个索引位置为分界点,左边比他大 右边比他小 自己位置是属于自己应有的位置 #返回这个位置 return left
#此函数是一个递归函数,用于一次次调用另外一个函数完成,对中间数据左右两边 # 放置左比自己小右边比自己大的数据, def quick_sort(li, left, right): if left < right: #接收返回的mid 这个位置 mid = partition(li, left, right) #然后再次调用自身,来排序 这个mid 左右两边的数据 quick_sort(li, left, mid - 1) quick_sort(li, mid + 1, right)
代码 正序 从小到大排
#快排 li = [5, 21, 3, 6, 2, 1, 7, 9, 8] li2=[4,3,1,6,8,2,5,7,9] #此函数是对数据处理的函数 #使用当前需要排序的列表段 即是索引区间位置的这些数据 def partition(li, left, right): #找到列表区间中最左边的数据 拿出来 悬空 # 然后开始和这个区间的数据进行对比 temp = li[left] #当右索引大于左索引的时候,证明 没有找到这个 temp的中间位置 # 并把他左右分别放置比自己大小的数据 while left < right: #用于比较temp 和从最右边的数据开始 的大小 ,只要是 这个右边的数据比 temp大 #则这个右边的数据当前位置正确,右索引减一, # 再次比较 当不符合while条件之 右边比temp小的时候 while left < right and temp < li[right]: right -= 1 #把当前右边的数据拿过来放到这个temp空出来的位置 li[left] = li[right] #然后开始比较左边的数据,同理 当不符合他的条件之左边数据大于temp时 while left < right and temp > li[left]: left += 1 #把这个数据拿出来,放到刚才空出来的 right索引位置 li[right] = li[left] # 直到left=right的时候,证明找到了 这个temp的索引位置 #把temp放到这个位置上去 li[left]=temp #此时以这个索引位置为分界点,左边比他大 右边比他小 自己位置是属于自己应有的位置 #返回这个位置 return left #此函数是一个递归函数,用于一次次调用另外一个函数完成,对中间数据左右两边 # 放置左比自己小右边比自己大的数据, def quick_sort(li, left, right): if left < right: #接收返回的mid 这个位置 mid = partition(li, left, right) #然后再次调用自身,来排序 这个mid 左右两边的数据 quick_sort(li, left, mid - 1) quick_sort(li, mid + 1, right) quick_sort(li, 0, len(li) - 1) print(li)
倒叙 从大到小排 只要把partition的大于号小于号翻转就行了
#快排 li = [5, 21, 3, 6, 2, 1, 7, 9, 8] li2=[4,3,1,6,8,2,5,7,9] #此函数是对数据处理的函数 #使用当前需要排序的列表段 即是索引区间位置的这些数据 def partition(li, left, right): #找到列表区间中最左边的数据 拿出来 悬空 # 然后开始和这个区间的数据进行对比 temp = li[left] #当右索引大于左索引的时候,证明 没有找到这个 temp的中间位置 # 并把他左右分别放置比自己大小的数据 while left < right: #用于比较temp 和从最右边的数据开始 的大小 ,只要是 这个右边的数据比 temp大 #则这个右边的数据当前位置正确,右索引减一, # 再次比较 当不符合while条件之 右边比temp小的时候 while left < right and temp > li[right]: right -= 1 #把当前右边的数据拿过来放到这个temp空出来的位置 li[left] = li[right] #然后开始比较左边的数据,同理 当不符合他的条件之左边数据大于temp时 while left < right and temp < li[left]: left += 1 #把这个数据拿出来,放到刚才空出来的 right索引位置 li[right] = li[left] # 直到left=right的时候,证明找到了 这个temp的索引位置 #把temp放到这个位置上去 li[left]=temp #此时以这个索引位置为分界点,左边比他大 右边比他小 自己位置是属于自己应有的位置 #返回这个位置 return left #此函数是一个递归函数,用于一次次调用另外一个函数完成,对中间数据左右两边 # 放置左比自己小右边比自己大的数据, def quick_sort(li, left, right): if left < right: #接收返回的mid 这个位置 mid = partition(li, left, right) #然后再次调用自身,来排序 这个mid 左右两边的数据 quick_sort(li, left, mid - 1) quick_sort(li, mid + 1, right) quick_sort(li, 0, len(li) - 1) print(li)
什么是最坏情况:
代码优化 避免出现最坏情况
#快排 li = [5, 21, 3, 6, 2, 1, 7, 9, 8] li2=[4,3,1,6,8,2,5,7,9] #此函数是对数据处理的函数 #使用当前需要排序的列表段 即是索引区间位置的这些数据 import random def partition(li, left, right): #找到列表区间中最左边的数据 拿出来 悬空 # 然后开始和这个区间的数据进行对比 #做一个随机取数据的函数,避免出现最坏情况 randi=random.randint(left,right) li[randi],li[left]=li[left],li[randi] temp = li[left] #当右索引大于左索引的时候,证明 没有找到这个 temp的中间位置 # 并把他左右分别放置比自己大小的数据 while left < right: #用于比较temp 和从最右边的数据开始 的大小 ,只要是 这个右边的数据比 temp大 #则这个右边的数据当前位置正确,右索引减一, # 再次比较 当不符合while条件之 右边比temp小的时候 while left < right and temp > li[right]: right -= 1 #把当前右边的数据拿过来放到这个temp空出来的位置 li[left] = li[right] #然后开始比较左边的数据,同理 当不符合他的条件之左边数据大于temp时 while left < right and temp < li[left]: left += 1 #把这个数据拿出来,放到刚才空出来的 right索引位置 li[right] = li[left] # 直到left=right的时候,证明找到了 这个temp的索引位置 #把temp放到这个位置上去 li[left]=temp #此时以这个索引位置为分界点,左边比他大 右边比他小 自己位置是属于自己应有的位置 #返回这个位置 return left #此函数是一个递归函数,用于一次次调用另外一个函数完成,对中间数据左右两边 # 放置左比自己小右边比自己大的数据, def quick_sort(li, left, right): if left < right: #接收返回的mid 这个位置 mid = partition(li, left, right) #然后再次调用自身,来排序 这个mid 左右两边的数据 quick_sort(li, left, mid - 1) quick_sort(li, mid + 1, right) quick_sort(li, 0, len(li) - 1) print(li)




注意 什么是堆

二:堆排
对排序的用的是
b=[2,8,1,4,9,6,5,7] def sift(data,low,high): #取出一个索引位置,从上向下调整 i=low #取一个索引 找到他的堆的下部位置 j=2*i+1 #把这个准备向下调整的数据保存到tmp这个变量中 tmp=data[i] while j<=high: #先判断他的孩子节点 的左右两个孩子的大小, #如果右孩子比较大的话就使用右孩子 if j<high and data[j] < data[j+1]: j+=1 #然后再用这个tmp跟他的比较大的孩子进行比较,如果他的孩子大于这个数值 if tmp<data[j]: #把这个tmp索引位置空出来给比较大的孩子 data[i]=data[j] #然后继续往下走,重新给i赋值 去继续往下走 判断他的孩子跟他的大小 i=j j=2*i+1 #当条件不成立的时候,则不做替换了跳出while循环 else: break #给 这是后把顶端的数据向下调整到这个i的位置上 data[i]=tmp #建堆函数 def heap_sort(data): #建堆是从后往前找 n=len(data) # n//2-1 就是第一个非叶子节点的节点, for i in range(n//2-1,-1,-1): #这里定义的n-1把他当左high最后的一个叶子节点所在索引位,所有的之地呢的数据都不会超过这个索引位置, #否则会发生索引越界 #取出这个data列表中从此跟节点到 n-1 去执行上边的向下调整函数 从 堆的底端开始调整 sift(data,i,n-1) for i in range(n-1,-1,-1):#i表示当前的high的值,也表示棋子的位置 #交换退休和要上去的值 data[0],data[i]=data[i],data[0] #此时堆的范围之0到i-1 因为取出来了一个少了一个 sift(data,0,i-1) heap_sort(b) print(b)
浙公网安备 33010602011771号