> 文章列表 > python3刷题小技巧

python3刷题小技巧

python3刷题小技巧

文章目录

  • list/tuple
    • list转置
    • 比较
  • 字符串
    • 字符串拼接
  • 数学
    • 10的几次方
    • 除法向上取整
    • 判断奇数/偶数
    • 只保留最右边的1,其他位全为0
    • 去掉最右边的1,保留其他位
    • 判断x是否为2的幂
  • 内置函数
    • zip
    • any, all
  • 内置数据结构
    • collections.deque
    • heapq/小根堆
    • bisect
    • itertools.permutations
    • itertools.combinations

list/tuple

list转置

x
[[1, 2, 3, 4], [1, 2, 3, 4]]
y = list(zip(*x))
y
[(1, 1), (2, 2), (3, 3), (4, 4)]

注意,转置后的矩阵,列表中的元素为tuple

比较

按照顺序,从前向后依次比较每个元素。当所有比较的元素都相同时,短的那个小

x = [1,2,3,4]
y = [1,2,3,4,5]
x > y
Falsex = [[1,2,3,4]]
y = [1,2,3,4,5]
x > y
TypeError: '>' not supported between instances of 'list' and 'int'

字符串

字符串拼接

在loop中不要用a += new_str,最好用list相加,最后再''.join(a_list),这样执行效率高

数学

10的几次方

1e1表示10的1次方,1e6表示10610^6106,注意结果是个float

除法向上取整

//是向下取整,有时候需要向上取整,即 希望能有:10 / 3 = 4
方法:(a + (b - 1)) // b
注意点:不适合负数

判断奇数/偶数

奇数:x & 1为1
偶数:x & 1为0
原因:奇数的最后1位为1,所以相与就还是1。偶数最后1位是0,相与之后就是0

只保留最右边的1,其他位全为0

x & (-x)
在这里插入图片描述

去掉最右边的1,保留其他位

x & (x - 1)
在这里插入图片描述

判断x是否为2的幂

x and (not (x & (x - 1)))

假设x是2的幂,如8,则满足:只有最高位是1,剩下的位都是0,此时x & (x - 1)应该是全0的,取个not,则变成逻辑值True
为了避免x本身是0造成的例外,前面再加个x and True,如果x = 0,则x and True = False,否则x and True = True,即x是2的幂

内置函数

zip

官方文档:https://docs.python.org/3/library/functions.html#zip
对于输入的iterable对象,每个对象取1个iter元素,直到最短的iterable对象结束

zip(*iterables)
# zip('ABCD', 'xy') --> Ax By# zip可以很方便地转置二维数组
a = [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]]
list(zip(*a))
>> [(1, 4, 7, 10), (2, 5, 8, 11), (3, 6, 9, 12)]# 这里的*a,是取了iterable对象a中的元素,也即4个1维数组,再对4个1维数组做zip

any, all

any会返回True,如果iterable对象中的元素有一个为True
all会返回True,当iterable对象中的所有元素为True

注:0认为是False

内置数据结构

collections.deque

官方文档:https://docs.python.org/zh-cn/3/library/collections.html
双向的list,在普通list外另有appendleft, popleft

普通的list,append(向尾部插入元素)和pop(删除尾部元素)时间复杂度都是o(1),但是对头部元素的操作是o(n),deque可以保证头部元素的操作时间复杂度也是o(1)

heapq/小根堆

官方文档:https://docs.python.org/zh-cn/3/library/heapq.html

如果想建大根堆,则排序的key取负数即可

堆的操作可以在所有iterable对象上进行,这里以list为例:

b = [1,6,8,4,2,1,8]import heapq
# 建堆
heapq.heapify(b)
# 此时b的内部已经是堆了
print(b)
>> [1, 2, 1, 4, 6, 8, 8]# 或者更常用的:
b = []
for item in iterable:heapq.heappush(b, item)
# 此时b是列表,后续的操作用heapq.heappush, heapq.heappop操作即可
# 建堆时,也可以使用元组,只要保证元组的第一个元素是sort_key即可,详见官方文档# push
heapq.heappush(b, 5)
>> [1, 2, 1, 4, 6, 8, 8, 5]# pop,弹出最小的元素
heapq.heappop(b)
>> 1
print(b)
>> [1, 2, 5, 4, 6, 8, 8]# 先push一个元素,再pop出最小的元素, 比手动heappush(), 再heappop()要快一些
heapq.heappushpop(b, 7)
>> 1
print(b)
>> [2, 4, 5, 7, 6, 8, 8]# 先pop最小的元素,再push元素,比手动heappop(),再heappush()快
heapq.heapreplace(b, 10)
>> 2
print(b)
>> [4, 6, 5, 7, 10, 8, 8]# 返回前n个最大的数
heapq.nlargest(4, b)
>> [10, 8, 8, 7]
# 返回前n个最小的数
heapq.nsmallest(4, b)
>> [4, 5, 6, 7]# 合并有序数组
heapq.merge(*iterables, key=None, reverse=False)

bisect

官方文档:https://docs.python.org/3/library/bisect.html
常用的是:
bisect.bisect_left(a, x, lo=0, hi=len(a)),意义是返回将x插入a[lo:hi]时的最左边索引
bisect.bisect_right(a, x, lo=0, hi=len(a))是最右边索引

二分查找可以写成:

import bisect# 找到target的第一个下标,如果不存在则返回-1
def find_first_index(nums: list, target: int) -> int:loc = bisect.bisect_left(nums, target)if loc != len(nums) and nums[loc] == target:return locreturn -1# 找到target的最后一个下标,如果不存在则返回-1
def find_last_index(nums: list, target: int) -> int:loc = bisect.bisect_right(nums, target)if nums[loc - 1] == target:return loc - 1return -1# 找到比target小的最大值,如果不存在返回-1
def find_smaller_greatest(nums: list, target: int) -> int:loc = bisect.bisect_left(nums, target)if loc:return nums[loc - 1]return -1

itertools.permutations

官方文档:https://docs.python.org/zh-cn/3/library/itertools.html

import itertools
list(itertools.permutations('abcd', 2))# out:
[('a', 'b'),('a', 'c'),('a', 'd'),('b', 'a'),('b', 'c'),('b', 'd'),('c', 'a'),('c', 'b'),('c', 'd'),('d', 'a'),('d', 'b'),('d', 'c')]

itertools.combinations

官方文档:https://docs.python.org/zh-cn/3/library/itertools.html

import itertools
list(itertools.combinations('abcd', 2))# out:
[('a', 'b'),('a', 'c'),('a', 'd'),('b', 'c'), ('b', 'd'), ('c', 'd')]