1.算法基础
算法(Algorithm):一个计算过程,解决问题的方法
递归回顾
递归式不能用函数装饰器的!如果你强用递归一次会执行一次你的幻术装饰器 避免这种情况可以在你使用的函数上加一层函数 例如: import functools import random import time import sys import os # 设置系统的最大递归限制 sys.setrecursionlimit(1000000) def run_time(func): """ 为了装饰别的函数,统计函数执行的时间统计 :param func: :return: """ @functools.wraps(func) def wrapper(*args,**kwargs): # 开始时间 start_time = time.time() # 调用被装饰的函数 res = func(*args,**kwargs) # 结束时间 end_time = time.time() # 打印输出,更佳的方法是将其写入到log中 print( "%s 函数的执行时间为: %s s" %(func.__name__,end_time - start_time)) return res return wrapper @run_time def fast_sort_1(data_list): """ 因为快排包含递归,所以不能直接被装饰,套一层外壳 :param data_list: :return: """ return fast_sort_basic1(data_list) def fast_sort_basic1(data_list): """简单的快速排序,消耗内存,空间复杂度略高""" if len(data_list) == 0: # 如果传过来的数据为[],直接返回 return [ ] else: # 把第一个数据拿出来, # 比它小的数据放在左边,再次调用本函数 + 第一个数据 + 比它小的数据放在右边,再次调用本函数 return fast_sort_basic1([i for i in data_list[1:] if i < data_list[0]]) + [data_list[0]] + fast_sort_basic1([i for i in data_list[1:] if i > data_list[0]])
递归 红色预警
1 使用递归完成 (抱着抱着我的小鲤鱼的我的我) 2 def output(cod,code=''): 3 if cod==0: 4 code += '我的小鲤鱼' 5 else: 6 code +='抱着' 7 code=output(cod - 1, code) 8 9 code += '的我' 10 return code 11 12 13 14 15 re=output(2,'') 16 print(re)
2.时间复杂度
时间复杂度是用来估计算法运行时间的一个式子(单位)。 一般来说,时间复杂度高的算法比复杂度低的算法慢 常见的时间复杂度(按效率排序) O(1)<O(logn)<O(n)<O(nlogn)<O(n2)<O(n2logn)<O(n3) 不常见的时间复杂度(看看就好) O(n!) O(2n) O(nn) … 如何一眼判断时间复杂度? 循环减半的过程O(logn) 几次循环就是n的几次方的复杂度
print('Hello World')
O(1) for i in range(n):
print('Hello World') O(n)
O(n2) for i in range(n):
print('Hello World') O(n3) while n > 1:
print(n)
n = n // 2 O(logn)
3.递归二分查找:
# 原理:必须是有序时间复杂长度O(lognn)
# 1.循环取最数列最中间的数据
# 同查找数据进行比较 如果比找的数据小,则把最后一个数据的位置提到中间位置-1,
# 同查找数据进行比较 如果比找的数据大,则把最后一个数据的位置提到中间位置+1
# 2.如果第一个位置的数据大于最后一个 执行完毕 没有找到
# 如果中间查找到终止
def bin_search(list_data, num):
l = 0
r = len(list_data) - 1
mid = (l + r) // 2
if list_data[mid] == num:
return mid
elif list_data[mid] > num:
high = mid - 1
else:
l = mid + 1
4.低级排序
1.冒泡排序(时间复杂度O(n2))常用
''' 冒泡排序原理: 一个指针指向当前数,如果当前数比下一个数据大 ,交换位置,指针往下走一帧 当前数比下一个数小,则指针往下走,当前数为指针所指向当数,和下一个数据比较 直到最后一个产生至少一个有序数据 指针再次回到第一个数据,重复动作 ''' def bubble_sort(list_data): for i in range(len(list_data)-1): flag=True for j in range(len(list_data)-i-1): if list_data[j]>list_data[j+1]: list_data[j],list_data[j+1]=list_data[j+1],list_data[j] flag =False if flag: return
2.选择排序(时间复杂度O(n2))
''' 选择排序原理: 先把左边第一个数当成最小的一个 进行便利所有的数据只要遇到比他小的就进行调换,直到完成一轮第一个最小 下一个依旧这样从当前的下一个进行便利调换 ''' def select_sort(li): for i in range(len(li)-1): min_loc=i for j in range(i+1,len(li)): if li[j]<li[min_loc] min_loc=j if min_loc !=i: li[i],li[min_loc]=li[min_loc],li[i]
3.插入排序(时间复杂度O(n2))
View Code
''' 插入排序原理: 数据中从左到右分为有序和无序区 先把第一个数当做有序的 下个数据从当前位置向前依次比较 遇到比自己小的第一个进行调换位置 依次编程有序的 ''' def insert_sort(list_data): for i in range(1,len(list_data)): tep=list_data[i] j=i-1 while j>=0 and tep <list_data[j]: list_data[j+1]=list_data[j] j=j-1 list_data[j+1]=tep
5.快排
option 1
import functools
import random
import time
import sys
import os
# 设置系统的最大递归限制
sys.setrecursionlimit(1000000)
def fast_sort(list_data): '''原理用内存还速度简单的快速排序,消耗内存,空间复杂度略高 以第一个数据为分界线 分为两部分左边 比中间的小 右边的比中间的大第一波下来找到最中间的值,并且分开大小 把左边的列表再次执行,分为三部分你, 右边的同样执行 ''' if len(list_data) == 0: return [] else: # 比它小的数据放在左边,再次调用本函数 + 第一个数据 + 比它小的数据放在右边,再次调用本函数 return fast_sort([i for i in list_data[1:] if i < list_data[0]]) + list_data[0] + fast_sort( [i for i in list_data[1:] if i > list_data[0]]) import random if __name__ == '__main__': a = list(range(33)) random.shuffle(a) # print(a) c = fast_sort_basic1(a) print(c)
option 2 不消耗内存
def fast_sort2(data,left,right): if left<right: # 调用partiton函数 mid 处为第一个元素应该待的地方 mid =partition(data,left,right) # 对左边的数据继续做快速排序 fast_sort2(data,left,mid-1) # 对右边的数据继续做快速排序 fast_sort2(data,mid+1,right) return data def partition(data,left,right): """ 找中间值 将数据的左边的第一个数据,数据调整为自己应该待的位置 [5,2,1,4,3] 从第一个数字开始,把它放在它应该在的位置,什么叫它应该在的位置,就是左边的数字都比它小,右边的数字都比它大 1、从最右边开始找,找到第一个比它小的数 和 它 交换位置,把第一个数字放到新的位置 2、然后从这个新的位置, 左边开始找比它大的数字,和它大小比较,然后和新的位置交换 3、不断重复,就会使第一个数字出现在它应该出现的位置 那么这个数字所在的位置就是有序区 """ # 找到左边的第一个数据 tmp = data[left] # 一直循环直到这个数据待在它自己该待的位置 while left < right: # 从右边开始找数据 while data[right] > tmp and left < right: # 找不到,继续往左找 right = right -1 # 右边找到一个比它小,赶紧交换位置 data[left] = data[right] # 从左边开始找数据 while data[left] < tmp and left < right: # 找不到继续往右找 left = left + 1 # 左边找到一个比它大的赶紧交换位置 data[right] = data[left] # 此时此刻左边和右边完全相同 # 这个数据已经待在它该待的位置 data[left] = tmp return left import random if __name__ == '__main__': a = list(range(12)) random.shuffle(a) print(a) c = fast_sort2(a,0,len(a)-1) print(c)