python基本算法
算法优劣评判标准
时间复杂度:
定义:用来评估算法运行效率的一个式子
print('Hello World') O(1)
for i in range(n):
print('Hello World') O(n)
for i in range(n):
for j in range(n):
print('Hello World') O(n^2)
for i in range(n):
for j in range(n):
for k in range(n):
print('Hello World') O(n^3)
注:O(1)、O(n)、O(n2)..是一个单位,且当n足够大时,n2的值可以忽略n的大小,所以计算时间复杂度时不会出现O(3)、O(n^2+n)的情况。
while n>1:
print(n)
n = n//2
输入:64
输出: 64 32 16 8 4 2
计算:2^6=64,执行次数6=log2 64
时间复杂度:O(logn)
小节:
时间复杂度是用来估计计算法运行时间的一个式子。
一般来说,时间复杂度高的算法比复杂度低的算法慢。
常见的时间复杂度(按效率排序)
O(1)<O(logn)<O(n)<O(nlogn)<O(n^2)<O(n^2logn)<O(n^3)
复杂问题的时间复杂度
O(n!) O(2^n) O(n^n)
如何简单快速地判断算法复杂度
- 确定问题规模n
- 循环减半过程 -》 logn
- k层关于n的循环 n^k
复杂情况:根据算法执行过程判断
空间复杂度
定义:用来评估算法内存占用大小的式子
空间复杂的表示方式与实践复杂度完全一样
算法使用了几个变量:O(1)
算法使用了长度为n的一位列表:O(n)
算法使用了m行n列的二维列表:O(mn)
空间换时间
递归算法
递归的两个特点:
- 调用自身
- 结束条件
递归:汉诺塔问题
def hanoi(n,a,b,c):
if n>0:
hanoi(n-1,a,c,b)
print("moving [%s] from %s to %s" %(n,a,c))
hanoi(n-1,b,a,c)
hanoi(3,"a","b","c")
查找问题
查找:在一些数据元素中,通过一定的方法找出与给定关键字相同的数据元素的过程
列表查找(线性表查找):从列表中产兆指定元素
输入:列表、待查找元素
输出:元素下表(未找到元素之一般返回None或-1)
内置列表查找函数:index()
方法一:顺序查找
顺序查找:也叫线性查找,从列表第一个元素开始,顺序进行搜索,直到找到元素或搜索到列表最后一个元素为止。
# 顺序查找
def linear_search(li,val):
for i,v in enumerate(li):
if v == val:
return i
else:
return None
#i = linear_search([1,2,3,6,7],6)
#print(i)
复杂度:O(n)
方法二:二分查找
二分查找:又叫折半查找,从有序列表的初始候选区li[0:n]开始,通过对待查找的值与候选区中间值的比较,可以使候选区减少一半。
# 二分法查找
def binary_search(li,val):
left,right = 0,len(li)-1
while left<=right: # 候选区有值
mid = (left+right)//2
if li[mid]==val:
return mid
elif li[mid]<val:
left = mid+1
else:
right = mid=1
else:
return None
i = binary_search([1,2,3,6,7],10)
print(i)
复杂度:O(logn)
对比:使用二分查找的速度远远大于顺序查找,但是二分查找只能应用于线性排序的列表。
列表排序
排序:将一组“无序”的记录序列调整为“有序的记录序列”。
列表排序:将无序列表变为有序列表
输入:列表
输出:有序列表
升序和降序
内置排序函数:sort()
冒泡排序
列表每两个相邻的数,如果前面比后面大,则交换这两个数。
一趟排序完成后,则无序区减少一个数,有序区增加一个数。
代码关键:趟,无序区范围。
#冒泡排序
def bubble_sort(li):
for i in range(len(li)-1):
for j in range(len(li)-i-1):
if li[j] > li[j+1]:
li[j],li[j+1] = li[j+1],li[j]
import random
li = [random.randint(1,1000) for _ in range(30)]
print(li)
bubble_sort(li)
print(li)
时间复杂度:O(n^2)
优化冒泡排序
#冒泡排序,当列表不再改变时 无需再循环
def bubble_sort(li):
for i in range(len(li)-1):
exchange = False
for j in range(len(li)-i-1):
if li[j] > li[j+1]:
li[j],li[j+1] = li[j+1],li[j]
exchange = True
print(li)
if not exchange:
return
import random
li = [1,2,3,7,6,8,9]
print(li)
bubble_sort(li)
选择排序
每次选出列表中最大值或者最小值,放在列表的首位或者末尾。
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
li[min_loc],li[i] = li[i],li[min_loc]
li = [1,2,3,7,6,8,9]
print(li)
select_sort(li)
print(li)
插入排序
拿到手里的牌和之前的所有牌比较,如果比之前的牌小,则记录该位置,最后记录的值就是手里的牌正确排序后的位置。
def insert_sort(li):
for i in range(len(li)):
tmp = li[i]
j = i - 1 # 候选区开头索引-1 就是有序区的结尾
while j >= 0 and tmp < li[j]:
li[j + 1] = li[j]
j -= 1
li[j + 1] = tmp
li = [9, 5, 6, 7, 3]
insert_sort(li)
快速排序
快速排序:快
快速排序思路:
取一个元素p(第一个元素),使元素p归位;
列表别p分成两部分,左边都比p小,右边都比p大;
递归完成排序。
def partition(li,left,right):
temp = li[left]
while left < right:
while left < right and li[right] >= temp:
right -= 1
li[left] = li[right]
while left < right and li[left] <= temp:
left += 1
li[right] = li[left]
li[left] = temp
return left
def quick_sort(li,left,right):
if left<right:
mid = partition(li,left,right)
quick_sort(li,left,mid-1)
quick_sort(li,left+1,right)
li = [9,4,3,6,8,15,3,31]
quick_sort(li,0,len(li)-1)
print(li)
快速排序的效率:
快速排序的时间复杂度 O(mlogn)
快速排序的问题:
最坏情况
递归
堆排序
树与二叉树
堆是一种特殊的完全二叉树
大根堆:一棵完全二叉树,满足任一节点都比其孩子节点大
小根堆:一棵完全二叉树,满足任一节点都比其孩子节点小
堆的向下调整:
假设:节点的左右子树都是堆,但是自身不是堆。
堆排序过程
堆排序过程:
- 建立堆。
- 得到堆顶元素,为最大元素。
- 去掉堆顶,将堆最后一个元素放到堆顶,此时可通过一次调整重新使堆有序。
- 堆顶元素为第二大元素。
- 重复步骤3,知道堆变空。
堆的向下调整
向下调整函数
def sift(li,low,high):
i = low
tmp = li[i]
j = i*2+1
while j<=high:
if j<high and li[j+1]>li[j]:
j = j+1
if tmp<=li[j]:
li[i]=li[j]
i = j
j = i*2+1
else:
break
li[i] = tmp
li = [1,9,8,7,6,5,0,2]
sift(li,0,len(li)-1)
print(li)
堆排序函数
def heap_sort(li):
n = len(li)
# 建堆
for i in range(n//2-1,-1,-1):
sift(li,i,n-1)
# 建堆完成
for i in range(n-1,-1,-1):
li[i],li[0]=li[0],li[i]
sift(li,0,i-1)
li = [2,6,4,6,8,5,3,10]
heap_sort(li)
print(li)
堆排序的内置模块heapq
import heapq
import random
li = list(range(100))
random.shuffle(li)
heapq.heapify(li)
print(li)
for i in range(len(li)-1):
print(heapq.heappop(li),end=' ')
归并排序
假设li是以mid为分界线的左右两边都是正序列表的列表
从头比较两边分列表的值,较小的取出放在新列表里,再比较该分列表下一个值和另一列表的当前值大小
def merge(li, low, mid, high):
i = low
j = mid + 1
ltmp = []
while i <= mid and j <= high:
if li[i] < li[j]:
ltmp.append(li[i])
i += 1
else:
ltmp.append(li[j])
j += 1
li[low:high + 1] = ltmp + li[i:mid + 1] + li[j:high + 1]
def merge_sort(li, low, high):
if low < high:
mid = (low + high) // 2
merge_sort(li, low, mid)
merge_sort(li, mid + 1, high)
merge(li, low, mid, high)
li = [3, 6, 4, 5, 8, 1, 2, 9, 0, 7]
merge_sort(li, 0, len(li) - 1)
python基本算法的更多相关文章
- Python基础算法综合:加减乘除四则运算方法
#!usr/bin/env python# -*- coding:utf-8 -*-#python的算法加减乘除用符号:+,-,*,/来表示#以下全是python2.x写法,3.x以上请在python ...
- xsank的快餐 » Python simhash算法解决字符串相似问题
xsank的快餐 » Python simhash算法解决字符串相似问题 Python simhash算法解决字符串相似问题
- python聚类算法实战详细笔记 (python3.6+(win10、Linux))
python聚类算法实战详细笔记 (python3.6+(win10.Linux)) 一.基本概念: 1.计算TF-DIF TF-IDF是一种统计方法,用以评估一字词对于一个文件集或一个语料库 ...
- python排序算法实现(冒泡、选择、插入)
python排序算法实现(冒泡.选择.插入) python 从小到大排序 1.冒泡排序: O(n2) s=[3,4,2,5,1,9] #count = 0 for i in range(len(s)) ...
- Python C3 算法 手动计算顺序
Python C3 算法 手动计算顺序 手动计算类继承C3算法原则: 以所求类的直接子类的数目分成相应部分 按照从左往右的顺序依次写出继承关系 继承关系第一个第一位,在所有后面关系都是第一个出现的 ...
- python聚类算法解决方案(rest接口/mpp数据库/json数据/下载图片及数据)
1. 场景描述 一直做java,因项目原因,需要封装一些经典的算法到平台上去,就一边学习python,一边网上寻找经典算法代码,今天介绍下经典的K-means聚类算法,算法原理就不介绍了,只从代码层面 ...
- python相关性算法解决方案(rest/数据库/json/下载)
1. 场景描述 一直做java,因项目原因,需要封装一些经典的算法到平台上去,就一边学习python,一边网上寻找经典算法代码,今天介绍下经典的相关性算法,算法原理就不介绍了,只从代码层面进行介绍,包 ...
- 关联规则 -- apriori 和 FPgrowth 的基本概念及基于python的算法实现
apriori 使用Apriori算法进行关联分析 貌似网上给的代码是这个大牛写的 关联规则挖掘及Apriori实现购物推荐 老师 Apriori 的python算法实现 python实现关联规则 ...
- Python排序算法之选择排序定义与用法示例
Python排序算法之选择排序定义与用法示例 这篇文章主要介绍了Python排序算法之选择排序定义与用法,简单描述了选择排序的功能.原理,并结合实例形式分析了Python定义与使用选择排序的相关操作技 ...
- 44.python排序算法(冒泡+选择)
一,冒泡排序: 是一种简单的排序算法.它重复地遍历要排序的数列,一次比较两个,如果他们的排序错误就把他们交换过来. 冒泡排序是稳定的(所谓稳定性就是两个相同的元素不会交换位置) 冒泡排序算法的运作如下 ...
随机推荐
- ffmpeg源码分析三:transcode_init函数 (转3)
原帖地址:http://blog.csdn.net/austinblog/article/details/25061945 transcode_init()函数是在转换前做准备工作的.下面看看其源代码 ...
- 简单的mysql热备
最近一直担心数据出问题,还好领导给了一台备用机,装好mysql后搜了下mysq热备相关的帖子,看似好繁琐,自己大概配置了一下擦发现起始很简单! 下边就是步骤了! 1.修改主从mysql配置文件,在my ...
- 如何安装和使用Karma-Jasmine
注意:本文中出现的资料链接.karma的插件安装等,均可能需要翻$墙后才能正确执行. Jasmine是一个JavaScript的测试工具,在Karma上运行Jasmine可完成Javascript的自 ...
- jquery中绑定click事件重复执行问题
jquery中单击事件重复多次执行的问题使用如下方式: $('#sub').unbind('click').click(function () { ... });
- 用jQuery获取table中行id和td值
<%@ page language="java" pageEncoding="UTF-8"%> <% String path = reques ...
- ubuntu18.04 安装显卡驱动
1.使用PPA仓库进行自动化安装 sudo add-apt-repository ppa:graphics-drivers/ppa && sudo apt update 2.查询所有u ...
- ubuntu tensorflow cpu Faster-RCNN配置参考
https://blog.csdn.net/qq_36652619/article/details/85006559 (参考) https://blog.csdn.net/zcy0xy/art ...
- StringBuffer详解
- web.xml配置详解[转]
引文: 对于一个J2EE领域的程序员而言,基本上每天都会和web应用打交道. 什么是web应用?最简单的web应用什么样?给你一个web应用你该从何入手? 1.什么是web应用? web应用是一种可以 ...
- Cocos2dx之touch事件
今天看了下ccocos2dx touch事件部分的源码,从CCTouch.CCTouchHandler和CCTouchDispatcher简单的做了分析和总结,先直接看源码吧! 1.CCTouch c ...