初学python之以时间复杂度去理解列表常见使用方法

列表list,一个有序的队列

列表内的个体为元素,由若干个元素按照顺序进行排列,列表是可变化的,也就是说可以增删

list定义

常用的列表定义方式: 使用[] 或者 a = list()

取数列表可以用range()

列表查询方法

index

index = 索引,以0开始查找

方法:value,[start,[stop]]

通过对应位置的索引进行查找,找到列表内的元素是否有匹配,如有则返回索引值

匹配到第一个元素则立即返回索引位

有时候从右边查找更加便利,比如反斜杠/ 从右边找更加便捷

例:

In [22]: a

Out[22]: [1, 2, 3, 5, 10, 20, 33, 55]

In [23]: a.index(3)

Out[23]: 2

In [24]: a.index(33)

Out[24]: 6

从右向左查找 index(value, [start, [stop]])

从某个值开始查找

In [46]: a.index(33,3)

Out[46]: 6

In [50]:a.index(55,-1)

Out[50]: 7

计算元素出现的次数

In [53]: a = [1,1,1,3,2,11,5,43,1,1]

In [54]: a.count(1)

Out[54]: 5

时间复杂度

计算机科学中,算法的时间复杂度是一个函数,它定性描述了该算法的运行时间。这是一个关于代表算法输入值的字符串的长度的函数。时间复杂度常用大O符号表述,不包括这个函数的低阶项和首项系数。使用这种方式时,时间复杂度可被称为是渐近的,它考察当输入值大小趋近无穷时的情况

index 和count 方法对应的时间复杂度

数学符号对应 O

O(n)

O(2)

O(1)

n表示多少个元素,意思为有多少个元素就从前到后多少个元素

将所有的元素都遍历一遍

需要考虑index方法和count方法适用性,是否该用,选型哪个需要考虑

随着列表数据规模增加而效率下降,如果能做到O1/2/3 这样则可以很快返回结果

list列表元素修改

对某一项索引位置赋值(修改)

In [59]: a

Out[59]: [1, 1, 1, 3, 2, 11, 5, 43, 1, 1]

In [60]: a[1] = 2

In [61]: a

Out[61]: [1, 2, 1, 3, 2, 11, 5, 43, 1, 1]

列表就地修改

对列表本身进行追加元素

lst.append(100)

[1, 2, 3, 2, 2, 5, 6, 100]

append 对list进行增加元素,返回一个None

In [71]: lst = [1,2,3,2,2,5,6]

In [72]: a = lst.append(100)

In [73]: type(a)

Out[73]: NoneType

In [74]: a

In [75]: print(a)

None

这里返回值为空

list运算

In [77]: a = [1,2,3]

In [78]: a * 3

Out[78]: [1, 2, 3, 1, 2, 3, 1, 2, 3]

这里有返回打印

有输出则是没有被就地修改,都是构造新的列表

我们看到增加之后原列表发生了变化,这样被称为就地修改,就地修改为只对当前列表进行修改,修改的是对象的本身

append对时间复杂度为O(1),因为通过索引进行修改,而且是从尾部进行修改

这样通过索引线性修改所耗时间很快,并非O(n) ,O(n)为逐步遍历,找到某个项再进行修改

insert 插入元素

In [81]: a.insert(1,‘a‘)

In [82]: a

Out[82]: [1, ‘a‘, 2, 3]

insert 为在指定处插入对象,这样会引起整个内存结构变化,所有数据统一向后错位,如果量级大则不要去做,尽可能new一个

所以尽可能避免挪动

insert时间复杂度为 O(n),如果放在开头则不建议,一般list规模很大,所以要考虑效率问题

所以,insert更适合链表方式

extend 将迭代对象追加

迭代对象不用解释了,可以是列表,可以是字典等等

b = {‘c‘:123}

In [85]: a.extend(b)

In [86]: a

Out[86]: [1, ‘a‘, 2, 3, ‘c‘]

追加迭代自己

In [88]: a.extend(a)

In [89]: a

Out[89]: [1, ‘a‘, 2, 3, ‘c‘, 1, ‘a‘, 2, 3,‘c‘]

remove 删除某个元素

remove 为删除某个内容,而并非索引

remove 为就地修改,在做位置的挪动,所以这里需要注重效率

In [89]: a

Out[89]: [1, ‘a‘, 2, 3, ‘c‘, 1, ‘a‘, 2, 3,‘c‘]

In [90]: a.remove(1)

In [91]: a

Out[91]: [‘a‘, 2, 3, ‘c‘, 1, ‘a‘, 2, 3,‘c‘]

In [92]: a.remove(1)

In [93]: a

Out[93]: [‘a‘, 2, 3, ‘c‘, ‘a‘, 2, 3, ‘c‘]

在顺序列表中,在中间包括开头,需要考虑效率问题

pop 弹出

从尾部进行弹出并且删除尾部的元素

In [103]: a = [1,2,3,11,13,12,20]

In [104]: a.pop()

Out[104]: 20

pop效率为O(1) 由于是在尾部进行就地修改,所以效率非常高

使用index进行pop,而索引则是从1开始并非是0

In [108]: a.pop(0)

Out[108]: 1

In [109]: a

Out[109]: [2, 3, 11, 13, 12]

pop的特性直接将前端显示,移除+修改并行操作

在清除对象过多的情况下,会引起大规模GC垃圾回收,同样要考虑到效率问题

list的排序

sort() 排序

In [113]: a = [63,1,44,2,19,94,64,21]

In [114]: a.sort()

In [115]: a

Out[115]: [1, 2, 19, 21, 44, 63, 64, 94]

reverse进行到排序

默认为: sort(Key=None,reverse=False)

默认情况下是升序排列,降序由大到小,那么进行到排序:

In [116]: a.sort(reverse=True)

In [117]: a

Out[117]: [94, 64, 63, 44, 21, 19, 2, 1]

但是当前如果遇到字符串则无法进行

In [117]: a

Out[117]: [94, 64, 63, 44, 21, 19, 2, 1]

In [118]: a.append(‘haha‘)

In [119]: a.sort(reverse=False)

---------------------------------------------------------------------------

TypeError                               Traceback (most recent call last)

<ipython-input-119-83555bcb738d> in<module>()

----> 1 a.sort(reverse=False)

TypeError: unorderable types: str() <int()

那么我们可以使用key=None 的方法进行对字符串排序

In [121]: a.sort(key=str)

In [122]: a

Out[122]: [1, 19, 2, 21, 44, 63, 64, 94,‘haha‘]

In [123]: a.sort(key=str,reverse=True)

In [124]: a

Out[124]: [‘haha‘, 94, 64, 63, 44, 21, 2,19, 1]

同样可以按照字母进行正排倒排

In [125]: a.append(‘ab‘)

In [126]: a.append(‘ba‘)

In [127]: a.sort(key=str,reverse=True)

In [128]: a

Out[128]: [‘haha‘, ‘ba‘, ‘ab‘, 94, 64, 63,44, 21, 2, 19, 1]

In [129]: a.sort(key=str)

In [130]: a

Out[130]: [1, 19, 2, 21, 44, 63, 64, 94,‘ab‘, ‘ba‘, ‘haha‘]

排序规则:将每个元素转为字符串,其都是直接转为ASCII码进行排序,这里的str为当前定义的函数,如果是自己写的函数可以自定义排序规则

取随机数

涉及random

choice 从非空序列的元素中随机选择

In [167]: a

Out[167]: [1, 19, 2, 21, 44, 63, 64, 94,‘ab‘, ‘ba‘, ‘haha‘]

In [168]: import random

In [169]: random.choice(a)

Out[169]: 1

In [170]: random.choice(a)

Out[170]: 64

randrange取之间的随机数的,以及步长

In [172]: random.randrange(1,10)

Out[172]: 5

shuffle 打乱元素

In [174]: random.shuffle(a)

In [175]: a

Out[175]: [94, 64, ‘ba‘, 21, 44, 19, 63, 2,1, ‘ab‘, ‘haha‘]

列表复制

== 和is 的区别

In [131]: lst0 = list(range(4))

In [132]: lst0

Out[132]: [0, 1, 2, 3]

In [133]: id(lst0)

Out[133]: 140196597896584

首先进行哈希匹配

In [134]: hash(id(lst0))

Out[134]: 140196597896584

给lst1 进行赋值 让其等于lst0

In [135]: lst1 = list(range(4))

In [136]: id(lst1)

Out[136]: 140196608816840

查看两个列表的值

In [138]: lst1

Out[138]: [0, 1, 2, 3]

In [139]: lst0

Out[139]: [0, 1, 2, 3]

In [140]: lst0 == lst1

Out[140]: True

In [141]: lst0 is lst1

Out[141]: False

通过以上,可以明白:

==   比较返回值 判断是否依次相等

is   比较内存地址是否一致

地址空间的引用

In [142]: id(lst0[1])

Out[142]: 9177888

In [143]: id(lst1[1])

Out[143]: 9177888

以上看到,是没有复制的过程,而是被引用了同样的内存地址空间

使用copy进行复制并返回一个新的列表

In [150]: lst0

Out[150]: [0, 1, 2, 3]

In [151]: lst5=lst0.copy()

In [152]: lst5

Out[152]: [0, 1, 2, 3]

使用= 进行拷贝

In [163]: lst5 = lst0

In [164]: lst0[1] = 555

In [165]: lst0

Out[165]: [0, 555, 2, 3]

In [166]: lst5

Out[166]: [0, 555, 2, 3]

因为赋值的是引用类型,所以直接将嵌套的list拷贝的内存地址

通过这个内存地址修改,则对两个list同时修改

需要注意的是:需要观察拷贝的类型是什么,不然会引起副作用,但是也可以通过特性批量进行操作

深拷贝和潜拷贝的基本概念

浅拷贝

在一般都是实现了浅拷贝,只拷贝了第一层结构,

被称为 shadow copy,但是引用的都是同一个内存地址

深拷贝

如果出现层次嵌套,会对引用类型进行深入拷贝,在结构上拷贝的一模一样,引用的内存地址则独立开辟

使用deepcopy可以进行深拷贝

使用list求100内的质数:

lst1 = []

for x in range(2,101):

for i in lst1:

if x % i == 0:

break

else:

lst1.append(x)

print(lst1)

时间: 2025-01-07 20:14:00

初学python之以时间复杂度去理解列表常见使用方法的相关文章

通过遍历而非排序求最值 python list in 时间复杂度 列表元素存在性

Write a function: def solution(A) that, given an array A of N integers, returns the smallest positive integer (greater than 0) that does not occur in A. For example, given A = [1, 3, 6, 4, 1, 2], the function should return 5. Given A = [1, 2, 3], the

初学Python语言者必须理解的下划线

下划线(_)在Python语言中有特殊作用. 在大多数编程语言中,下划线是命名变量或者函数名称时的连字符,但是,在Python语言中,不仅如此.如果你是一名Python程序员,对于诸如 _ in range(10) , __init__(self) 之类的下发肯定熟知. 本文将详述下划线(_)的使用方法,帮助初学者理解它. 在Python语言中,下划线主要应用在如下5个方面: 在交互模式中,保存最近一个表达式的值 忽略某个值(“我不重要”) 给变量或者函数名称赋予特殊含义 作为国际化或本地化的函

Python 多进程实战 & 回调函数理解与实战

这篇博文主要讲下笔者在工作中Python多进程的实战运用和回调函数的理解和运用. 多进程实战 实战一.批量文件下载 从一个文件中按行读取 url ,根据 url 下载文件到指定位置,用多进程实现. #!/usr/local/python27/bin/python2.7 from multiprocessing import Process,Pool import os,time,random,sys import urllib # 文件下载函数 def filedown(url,file):  

Python基础教程(第二章 列表和元组)

本文内容全部出自<Python基础教程>第二版,在此分享自己的学习之路. ______欢迎转载:http://www.cnblogs.com/Marlowes/p/5293195.html______ Created on Xu Hoo 本章将引入一个新的概念:数据结构.数据结构是通过某种方式(例如对元素进行编号)组织在一起的数据元素的集合,这些数据元素可以是数字或者字符,甚至可以是其他数据结构.在Python中,最基本的数据结构是序列(sequence),序列中的每个元素被分配一个序号——即

【初学python】错误SSLError: [Errno 1] _ssl.c:504:的解决记录

最近在实习公司学习使用python做web自动化测试,其中使用到httplib这个模板,主要用于与待测试界面建立HTTP连接,发送数据请求,接收请求状态码和查询数据,验证功能.但是新版本的web界面改成使用https协议,原来的测试用例都变成无法跑通的状态. 将协议从HTTP改成HTTPS后,报以下错误: SSLError: [Errno 1] _ssl.c:504: error:140770FC:SSL routines:SSL23_GET_SERVER_HELLO:unknown proto

初学Python(九)——函数

初学Python(九)--函数 初学Python,主要整理一些学习到的知识点,这次是函数. 函数定义: # -*- coding:utf-8 -*- #函数的定义 def my_function(x): if x>0: return x elif x<0: return -x else: pass #函数的调用 a = my_function(-1) b = my_function(2) c = my_function(0) print a,b,c #空函数,pass为占位符 def empt

初学 Python(十四)——生成器

初学 Python(十四)--生成器 初学 Python,主要整理一些学习到的知识点,这次是生成器. # -*- coding:utf-8 -*- ''''' 生成式的作用: 减少内存占有,不用一次性 创建list中所有的元素,而 是在需要的时候创建 ''' #创建generator有2种方式 #第一种将列表表达式中的[]改为()即可 g = (x*x for x in range(10)) print g for n in g: print n #第二种,关键字yield def fab(ma

换种思路去理解设计模式(下)

开写之前,先把前两部分的链接贴上.要看此篇,不许按顺序看完前两部分,因为这本来就是一篇文章,只不过内容较多,分开写的. 换种思路去理解设计模式(上) 换种思路去理解设计模式(中) 8       对象行为与操作对象 8.1     过程描述 所谓对象行为和操作对象,需要三方面内容: l  操作过程: 一般表现为一个方法.该方法接收一个对象或者组合类型的参数,然后对这个对象或者组合进行操作,例如修改属性.状态或者结构等. l  操作的对象或组合: 会作为实参传入操作过程,会被操作过程修改属性.状态

对Python装饰器的个人理解方法

0.说明 在自己好好总结并对Python装饰器的执行过程进行分解之前,对于装饰器虽然理解它的基本工作方式,但对于存在复杂参数的装饰器(装饰器和函数本身都有参数),总是会感到很模糊,即使这会弄懂了,下一次也很快忘记,其实本质上还是没有多花时间去搞懂其中的细节问题. 虽然网络上已经有很多这样的文章,但显然都是别人的思想,因此自己总是记不牢,所以花点时间自己好好整理一下. 最近在对<Python核心编程>做总结,收获了不少,下面分享一下我自己对于Python装饰器的理解,后面还提供了一个较为复杂的P