LeetCode----Python 基础知识
0 python 基础知识
0.1 深拷贝、浅拷贝
在 Python 中,复制一个对象有两种方式:浅拷贝和深拷贝。
浅拷贝(Shallow Copy)
浅拷贝是指创建一个新的对象,但只复制原始对象中的最外层元素,而不是递归地复制所有子对象。也就是说,新对象中包含的子对象实际上是原始对象中对应子对象的引用,而不是副本。
在 Python 中,可以使用切片操作或者 copy() 方法进行浅拷贝。
>>> a = [1, 2, [3, 4]]
>>> b = a[:] # 或者使用 b = a.copy()
>>> b[0] = 10
>>> b[2][0] = 30
>>> print(a)
[1, 2, [30, 4]]
>>> print(b)
[10, 2, [30, 4]]
上述代码中,我们先创建了一个包含一个整数和一个列表的列表 a。然后,使用切片操作或者 copy() 方法对其进行浅拷贝,得到了另一个列表 b。接着,我们修改了 b 中的第一个元素和第三个元素的第一个元素,发现这两个操作都影响了原始列表 a,因为它们共享了同一个子列表。
深拷贝(Deep Copy)
深拷贝是指创建一个新的对象,并递归地复制原始对象中所有子对象,而不是仅复制最外层元素。也就是说,新对象中包含的所有子对象都是原始对象中对应子对象的副本,而不是引用。
在 Python 中,可以使用 copy.deepcopy() 方法进行深拷贝。
>>> import copy
>>> a = [1, 2, [3, 4]]
>>> b = copy.deepcopy(a)
>>> b[0] = 10
>>> b[2][0] = 30
>>> print(a)
[1, 2, [3, 4]]
>>> print(b)
[10, 2, [30, 4]]
上述代码中,我们首先导入了 copy 模块,然后使用 deepcopy() 方法对列表 a 进行深拷贝,得到了一个新的列表 b。接着,我们修改了 b 中的第一个元素和第三个元素的第一个元素,发现这两个操作并没有影响到原始列表 a,因为它们使用了不同的子列表。
0.2 Python计数的Counter类
主要用于快速的统计元素个数。Counter 是 dict 字典的子类,Counter 拥有类似字典的 key 键和 value 值,只不过 Counter 中的键为待计数的元素,而 value 值为对应元素出现的次数 count。
从 string(字符为list列表的元素)、list 和 tuple 这些可迭代对象中获取元素。
from collections import Counter
# 从可迭代对象中实例化 Counter
b = Counter("chenkc") # string
b2 = Counter(['c', 'h', 'e', 'n', 'k', 'c']) # list
b3 = Counter(('c', 'h', 'e', 'n', 'k', 'c')) # tuple
>>> print(b)
Counter({'c': 2, 'h': 1, 'e': 1, 'n': 1, 'k': 1})
>>> print(b2)
Counter({'c': 2, 'h': 1, 'e': 1, 'n': 1, 'k': 1})
>>> print(b3)
Counter({'c': 2, 'h': 1, 'e': 1, 'n': 1, 'k': 1})
1 python 常用函数
1.1 排序函数
原地排序 nums.sort()
不改变原列表,有返回值 new = sorted(nums)
import functools
# 一维数组排序
nums = [2, 1, 3, 4, 5]
def compare_udf(x, y):
# x - y 升序
# y - x 降序
return x - y
# # python2
nums.sort(cmp=compare_udf)
# # python3
nums.sort(key=functools.cmp_to_key(compare_udf))
print(nums)
二维数组排序
nums = [(264.0, 8, 0), (199.0, 10, 1), (230.0, 10, 2), (199.0, 9, 3)]
# 基础排序 按照一维升序排列,按照二维降序排列
new = sorted(nums, key=lambda x: (x[0], -x[1]))
print(new)
# 自定义排序
import functools
def comp(x, y):
if x[0] != y[0]:
return x[0] - y[0]
else:
return y[1] - x[1]
new = sorted(nums, key=functools.cmp_to_key(comp))
print(new)
字典排序
class Solution:
def cmp(self,x,y):
return y[0] - x[0]
def isIsomorphic(self, s: str, t: str) -> bool:
d = {1:"c",2:"d"}
# 按value 倒叙排列
d1 = sorted(d.items(), key = lambda x:x[1], reverse=True)
print(d1)
# 按key 倒叙排列
d2 = sorted(d.items(), key=functools.cmp_to_key(self.cmp))
print(d2)
return True
1.2 最大值、最小值
max(nums)
max(2,3)
min(2,3)
1.3 随机数
import random
# 生成一个0到1的随机符点数: 0 <= n < 1.0
print( random.random() )
# 生成一个指定范围内的随机符点数,两个参数其中一个是上限,一个是下限。
# 如果a > b,则生成的随机数n: b <= n <= a。如果 a <b, 则 a <= n <= b
print (random.uniform(1, 10)
# 生成一个指定范围内的整数。其中参数a是下限,参数b是上限,生成的随机数n: a <= n <= b
print( random.randint(1,10) )
# 函数原型为:random.randrange([start], stop[, step]),从指定范围内,按指定基数递增的集合中 获取一个随机数。
# 如:random.randrange(10, 100, 2),结果相当于从[10, 12, 14, 16, ... 96, 98]序列中获取一个随机数。
# random.randrange(10, 100, 2)在结果上与 random.choice(range(10, 100, 2) 等效。
print (random.randrange(10, 18, 2))
# 函数原型为:random.choice(sequence)。参数sequence表示一个有序类型。
# 这里要说明 一下:sequence在python不是一种特定的类型,而是泛指一系列的类型。list, tuple, 字符串都属于sequence。
print (random.choice(["python", "tab", "com"]))
# random.shuffle的函数原型为:random.shuffle(x[, random]),用于将一个列表中的元素打乱。
list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
random.shuffle(list)
print (list)
# 函数原型为:random.sample(sequence, k),从指定序列中随机获取指定长度的片断。
# sample函数不会修改原有序列。
list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
slice = random.sample(list, 5) #从list中随机获取5个元素,作为一个片断返回
print (slice)
print (list) #原有序列不会改变。
3 数据结构
3.1 基本数据类型
3.1 数组
3.2 队列
queue 模块简介
queue模块是Python内置的标准模块,模块实现了三种类型的队列,它们的区别仅仅是条目取回的顺序,分别由3个类进行表示,Queue,LifoQueue,PriorityQueue。
3.2.1 class queue.Queue(maxsize=0)
Constructor for a FIFO queue. maxsize is an integer that sets the upperbound limit on the number of items that can be placed in the queue. Insertion will block once this size has been reached, until queue items are consumed. If maxsize is less than or equal to zero, the queue size is infinite.
3.2.2 class queue.LifoQueue(maxsize=0)
LIFO 队列构造函数。 maxsize 是个整数,用于设置可以放入队列中的项目数的上限。当达到这个大小的时候,插入操作将阻塞至队列中的项目被消费掉。如果 maxsize 小于等于零,队列尺寸为无限大。
3.2.3 class queue.PriorityQueue(maxsize=0)
优先级队列构造函数。 maxsize 是个整数,用于设置可以放入队列中的项目数的上限。当达到这个大小的时候,插入操作将阻塞至队列中的项目被消费掉。如果 maxsize 小于等于零,队列尺寸为无限大。
最小值先被取出( 最小值条目是由 sorted(list(entries))[0] 返回的条目)。条目的典型模式是一个以下形式的元组: (priority_number, data) 。
如果 data 元素没有可比性,数据将被包装在一个类中,忽略数据值,仅仅比较优先级数字 :
from dataclasses import dataclass, field
from typing import Any
@dataclass(order=True)
class PrioritizedItem:
priority: int
item: Any=field(compare=False)
3.2.4 class queue.SimpleQueue
无界的 FIFO 队列构造函数。简单的队列,缺少任务跟踪等高级功能。
3.2.5 Queue 对象
队列对象(Queue,LiFoQueue,或者PriorityQueue)提供下列描述的公共方法。
Queue.qsize()
返回队列的大致大小。注意,qsize() > 0 不保证后续的 get() 不被阻塞,qsize() < maxsize 也不保证 put() 不被阻塞。
Queue.empty()
如果队列为空,返回 True ,否则返回 False 。如果 empty() 返回 True ,不保证后续调用的 put() 不被阻塞。类似的,如果 empty() 返回 False ,也不保证后续调用的 get() 不被阻塞。
Queue.full()
如果队列是满的返回 True ,否则返回 False 。如果 full() 返回 True 不保证后续调用的 get() 不被阻塞。类似的,如果 full() 返回 False 也不保证后续调用的 put() 不被阻塞。
Queue.put(item, block=True, timeout=None)
将 item 放入队列。如果可选参数 block 是 true 并且 timeout 是 None (默认),则在必要时阻塞至有空闲插槽可用。如果 timeout 是个正数,将最多阻塞 timeout 秒,如果在这段时间没有可用的空闲插槽,将引发 Full 异常。反之 (block 是 false),如果空闲插槽立即可用,则把 item 放入队列,否则引发 Full 异常 ( 在这种情况下,timeout 将被忽略)。
Queue.put_nowait(item)
相当于 put(item, False) 。
Queue.get(block=True, timeout=None)
从队列中移除并返回一个项目。如果可选参数 block 是 true 并且 timeout 是 None (默认值),则在必要时阻塞至项目可得到。如果 timeout 是个正数,将最多阻塞 timeout 秒,如果在这段时间内项目不能得到,将引发 Empty 异常。反之 (block 是 false) , 如果一个项目立即可得到,则返回一个项目,否则引发 Empty 异常 (这种情况下,timeout 将被忽略)。
POSIX系统3.0之前,以及所有版本的Windows系统中,如果 block 是 true 并且 timeout 是 None , 这个操作将进入基础锁的不间断等待。这意味着,没有异常能发生,尤其是 SIGINT 将不会触发 KeyboardInterrupt 异常。
Queue.get_nowait()
相当于 get(False) 。
提供了两个方法,用于支持跟踪 排队的任务 是否 被守护的消费者线程 完整的处理。
Queue.task_done()
表示前面排队的任务已经被完成。被队列的消费者线程使用。每个 get() 被用于获取一个任务, 后续调用 task_done() 告诉队列,该任务的处理已经完成。
如果 join() 当前正在阻塞,在所有条目都被处理后,将解除阻塞(意味着每个 put() 进队列的条目的 task_done() 都被收到)。
如果被调用的次数多于放入队列中的项目数量,将引发 ValueError 异常 。
Queue.join()
阻塞至队列中所有的元素都被接收和处理完毕。
当条目添加到队列的时候,未完成任务的计数就会增加。每当消费者线程调用 task_done() 表示这个条目已经被回收,该条目所有工作已经完成,未完成计数就会减少。当未完成计数降到零的时候, join() 阻塞被解除。
示例代码
from queue import Queue
queue_ = Queue()
queue_.put(1)
queue_.put(2)
queue_.put(3)
print(list(queue_.queue)) # 快速打印一个队列
print(queue_.get())
print(list(queue_.queue))
queue_.put(4, block=True) # 当超出最大长度时就会报错
queue_.get(block=True) # 如果队列为空,仍然继续取元素,会发生报错
[1, 2, 3]
1
[2, 3]
3.3 defaultdict
Python中通过Key访问字典,当Key不存在时,会引发‘KeyError’异常。为了避免这种情况的发生,可以使用collections类中的defaultdict()方法来为字典提供默认值
defaultdict是内置数据类型dict的一个子类,基本功能与dict一样,只是重写了一个方法missing(key)和增加了一个可写的对象变量default_factory
3.3.1 列表字典
使用list作为default_factory,很容易将一个key-value的序列转换为list字典;
from collections import defaultdict
s = [('yellow', 1), ('blue', 2), ('yellow', 3), ('blue', 4), ('red', 1)]
d = defaultdict(list)
for k, v in s:
d[k].append(v)
a = d.items()
print(a)
b = sorted(d.items())
print(b)
"""
结果:
dict_items([('yellow', [1, 3]), ('blue', [2, 4]), ('red', [1])])
[('blue', [2, 4]), ('red', [1]), ('yellow', [1, 3])]
"""
> 当字典中没有的键第一次出现时,default_factory自动为其返回一个空列表,list.append()会将值添加进新列表;再次遇到相同的键时,list.append()将其它值再添加进该列表。
这种方法比使用dict.setdefault()更为便捷,dict.setdefault()也可以实现相同的功能。
3.3.2 计数字典
from collections import defaultdict
# 当字典不存在某个键时指定默认值
# 1 指定默认类型
# 2 使用匿名函数
dict1 = defaultdict(int)
print(dict1["a"])
dict2 = defaultdict(lambda: 0)
print(dict2["a"])
dict3 = defaultdict(lambda: [0, 0])
print(dict3["a"])
0
0
[0, 0]
3.3.3 集合字典
将default_factory设置为set,使得defaultdict可以建立一个集合字典
from collections import defaultdict
s = [('red', 1), ('blue', 2), ('red', 3), ('blue', 4), ('red', 1), ('blue', 4)]
d = defaultdict(set)
for k, v in s:
d[k].add(v)
a = d.items()
print(a)
b = sorted(d.items())
print(b)
dict_items([('red', {1, 3}), ('blue', {2, 4})])
[('blue', {2, 4}), ('red', {1, 3})]
3.4 优先队列
import heapq
"""
默认结构为最小堆
最大堆实现:元素入堆时,取反。出堆时,再次取反。
"""
# 1. 创建堆
# 方法1:定义一个空列表,然后使用 heapq.heapqpush(item) 函数把元素加入到堆中
print("*" * 5 + "1" + "*" * 5)
item = 2
heap = []
heapq.heappush(heap, item)
print(heap)
# 方法2:使用 heapq.heapqify(list) 将列表转换为堆结构
heap = [2, 0, 4, 1]
heapq.heapify(heap)
print(heap)
# 2. heapq.heappush(heap, num) 添加新元素
print("*" * 5 + "2" + "*" * 5)
num = 5
heapq.heappush(heap, num)
print(heap)
# 3. heapq.heappop(heap) 删除并返回堆顶元素
print("*" * 5 + "3" + "*" * 5)
print(heapq.heappop(heap))
print(heap)
# 4. heapq.heappushpop(heap, num) 比较添加元素域堆顶元素的大小:
# 如果 num > 堆顶元素,删除并返回堆顶元素,然后添加新元素 num
# 如果 num < 堆顶元素,返回num,原堆不变
print("*" * 5 + "4" + "*" * 5)
num = 0
heapq.heappushpop(heap, num)
print(heap)
# 5. heapq.heapreplace(heap, num) 删除并返回堆顶元素,然后添加新元素
print("*" * 5 + "5" + "*" * 5)
num = 6
heapq.heapreplace(heap, num)
print(heap)
# 6. heap = heapq.merge(heap1, heap2)
# 合并多个排序后的序列成一个排序后的序列,返回排序后的值的迭代器
print("*" * 5 + "6" + "*" * 5)
heap1 = [1, 3, 4, 6]
heap2 = [2, 4, 5, 6]
heap = heapq.merge(heap1, heap2)
print(list(heap))
# 7. heapq.nsmallest(n, heap) 查询堆中的最小n个元素
print("*" * 5 + "7" + "*" * 5)
n = 3
heap = [2, 4, 5, 6]
print(heapq.nsmallest(n, heap))
# 8. heapq.nlargest(n, heap) 查询堆中的最大n个元素
print("*" * 5 + "8" + "*" * 5)
n = 3
heap = [2, 4, 5, 6]
print(heapq.nlargest(n, heap))
# 9. 最大堆实现
print("*" * 5 + "9" + "*" * 5)
heap = [2, 4, 5, 6]
heap = [item * -1 for item in heap]
heapq.heapify(heap)
print(-1 * heap[0])
*****1*****
[2]
[0, 1, 4, 2]
*****2*****
[0, 1, 4, 2, 5]
*****3*****
0
[1, 2, 4, 5]
*****4*****
[1, 2, 4, 5]
*****5*****
[2, 5, 4, 6]
*****6*****
[1, 2, 3, 4, 4, 5, 6, 6]
*****7*****
[2, 4, 5]
*****8*****
[6, 5, 4]
*****9*****
6
进程已结束,退出代码0

浙公网安备 33010602011771号