Python学习笔记3
回文判断
一、双端队列(deque)
deque是一种双端队列,同时具有栈和队列的特征,可以从序列的任何一端添加和删除项。进行回文判断时,通过函数popleft()和pop()分别去掉最左和最右的项并返回,向中间扫描,直到两端字符匹配,到达中间。
# deque双端序列
def palindrome(word):
from collections import deque
dq = deque(word)
while len(dq) > 1:
if dq.popleft() != dq.pop():
return False
return True
二、列表反向切片
快速判断回文
# 反向切片
def another_palindrome(word):
return word == word[::-1]
这两种方法都可以判断整个字符串是否是回文字符串,但是不能找出一组不符合回文的字符串中最长的回文字符。
反向切片同样可以用在字符串、数字逆序,注意符号的位置即可
itertools迭代器函数
无穷迭代器:
itertools.count(start=0, step=1)
创建一个迭代器,它从 start 值开始,返回均匀间隔的值。常用于 map() 中的实参来生成连续的数据点。此外,还用于 zip() 来添加序列号。
count(10) --> 10 11 12 13 14 …
count(2.5, 0.5) -> 2.5 3.0 3.5 …
def count(start=0, step=1):
# count(10) --> 10 11 12 13 14 ...
# count(2.5, 0.5) -> 2.5 3.0 3.5 ...
n = start
while True:
yield n
n += step
itertools.cycle(iterable)
创建一个迭代器,返回 iterable 中所有元素并保存一个副本。当取完 iterable 中所有元素,返回副本中的所有元素。无限重复。
cycle(‘ABCD’) --> A B C D A B C D …
def cycle(iterable):
# cycle('ABCD') --> A B C D A B C D A B C D ...
saved = []
for element in iterable:
yield element
saved.append(element)
while saved:
for element in saved:
yield element
itertools.repeat(object[, times])
创建一个迭代器,不断重复 object 。除非设定参数 times ,否则将无限重复。可用于 map() 函数中的参数,被调用函数可得到一个不变参数。也可用于 zip() 的参数以在元组记录中创建一个不变的部分。
repeat(10, 3) --> 10 10 10
def repeat(object, times=None):
# repeat(10, 3) --> 10 10 10
if times is None:
while True:
yield object
else:
for i in range(times):
yield object
repeat 最常见的用途就是在 map 或 zip 提供一个常量流:
>>> list(map(pow, range(10), repeat(2)))
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
根据最短输入序列长度停止的迭代器:
itertools.accumulate(iterable[, func, *, initial=None])
创建一个迭代器,返回累积汇总值或其他双目运算函数的累积结果值(通过可选的 func 参数指定)。
如果提供了 func,它应当为带有两个参数的函数。 输入 iterable 的元素可以是能被 func 接受为参数的任意类型。 (例如,对于默认的加法运算,元素可以是任何可相加的类型包括 Decimal 或 Fraction。)
通常,输出的元素数量与输入的可迭代对象是一致的。 但是,如果提供了关键字参数 initial,则累加会以 initial 值开始,这样输出就比输入的可迭代对象多一个元素。
accumulate([1,2,3,4,5]) --> 1 3 6 10 15
accumulate([1,2,3,4,5], operator.mul) --> 1 2 6 24 120
accumulate([1,2,3,4,5], initial=100) --> 100 101 103 106 110 115
def accumulate(iterable, func=operator.add, *, initial=None):
'Return running totals'
# accumulate([1,2,3,4,5]) --> 1 3 6 10 15
# accumulate([1,2,3,4,5], initial=100) --> 100 101 103 106 110 115
# accumulate([1,2,3,4,5], operator.mul) --> 1 2 6 24 120
it = iter(iterable)
total = initial
if initial is None:
try:
total = next(it)
except StopIteration:
return
yield total
for element in it:
total = func(total, element)
yield total
itertools.chain(*iterables)
创建一个迭代器,它首先返回第一个可迭代对象中所有元素,接着返回下一个可迭代对象中所有元素,直到耗尽所有可迭代对象中的元素。可将多个序列处理为单个序列。
chain(‘ABC’, ‘DEF’) --> A B C D E F
def chain(*iterables):
# chain('ABC', 'DEF') --> A B C D E F
for it in iterables:
for element in it:
yield element
vs
chain.from_iterable([‘ABC’, ‘DEF’]) --> A B C D E F
def from_iterable(iterables):
# chain.from_iterable(['ABC', 'DEF']) --> A B C D E F
for it in iterables:
for element in it:
yield element
两者输入格式不同
itertools.compress(data, selectors)
创建一个迭代器,它返回 data 中经 selectors 真值测试为 True 的元素。迭代器在两者较短的长度处停止。
compress(‘ABCDEF’, [1,0,1,0,1,1]) --> A C E F
def compress(data, selectors):
# compress('ABCDEF', [1,0,1,0,1,1]) --> A C E F
return (d for d, s in zip(data, selectors) if s)
itertools.filterfalse(predicate, iterable)
创建一个迭代器,只返回 iterable 中 predicate 为 False 的元素。如果 predicate 是 None,返回真值测试为false的元素。
filterfalse(lambda x: x%2, range(10)) --> 0 2 4 6 8
def filterfalse(predicate, iterable):
# filterfalse(lambda x: x%2, range(10)) --> 0 2 4 6 8
if predicate is None:
predicate = bool
for x in iterable:
if not predicate(x):
yield x
排列组合迭代器:
itertools.product(*iterables, repeat=1)
可迭代对象输入的笛卡儿积。
大致相当于生成器表达式中的嵌套循环。例如, product(A, B) 和 ((x,y) for x in A for y in B) 返回结果一样。
嵌套循环像里程表那样循环变动,每次迭代时将最右侧的元素向后迭代。这种模式形成了一种字典序,因此如果输入的可迭代对象是已排序的,笛卡尔积元组依次序发出。
要计算可迭代对象自身的笛卡尔积,将可选参数 repeat 设定为要重复的次数。例如,product(A, repeat=4) 和 product(A, A, A, A) 是一样的。
product(‘ABCD’, repeat=2)
AA AB AC AD BA BB BC BD CA CB CC CD DA DB DC DD
def product(*args, repeat=1):
# product('ABCD', 'xy') --> Ax Ay Bx By Cx Cy Dx Dy
# product(range(2), repeat=3) --> 000 001 010 011 100 101 110 111
pools = [tuple(pool) for pool in args] * repeat
result = [[]]
for pool in pools:
result = [x+[y] for x in result for y in pool]
for prod in result:
yield tuple(prod)
itertools.permutations(iterable, r=None)
连续返回由 iterable 元素生成长度为 r 的排列。
如果 r 未指定或为 None ,r 默认设置为 iterable 的长度,这种情况下,生成所有全长排列。
排列元组会以字典顺序根据所输入 iterable 的顺序发出。 因此,如果所输入 iterable 是已排序的,组合元组也将按已排序的顺序生成。
即使元素的值相同,不同位置的元素也被认为是不同的。如果元素值都不同,每个排列中的元素值不会重复。
permutations(‘ABCD’, 2)
AB AC AD BA BC BD CA CB CD DA DB DC
def permutations(iterable, r=None):
# permutations('ABCD', 2) --> AB AC AD BA BC BD CA CB CD DA DB DC
# permutations(range(3)) --> 012 021 102 120 201 210
pool = tuple(iterable)
n = len(pool)
r = n if r is None else r
if r > n:
return
indices = list(range(n))
cycles = list(range(n, n-r, -1))
yield tuple(pool[i] for i in indices[:r])
while n:
for i in reversed(range(r)):
cycles[i] -= 1
if cycles[i] == 0:
indices[i:] = indices[i+1:] + indices[i:i+1]
cycles[i] = n - i
else:
j = cycles[i]
indices[i], indices[-j] = indices[-j], indices[i]
yield tuple(pool[i] for i in indices[:r])
break
else:
return
itertools.combinations(iterable, r)
返回由输入 iterable 中元素组成长度为 r 的子序列。
组合元组会以字典顺序根据所输入 iterable 的顺序发出。 因此,如果所输入 iterable 是已排序的,组合元组也将按已排序的顺序生成。
即使元素的值相同,不同位置的元素也被认为是不同的。如果元素各自不同,那么每个组合中没有重复元素。
combinations(‘ABCD’, 2)
AB AC AD BC BD CD
def combinations(iterable, r):
# combinations('ABCD', 2) --> AB AC AD BC BD CD
# combinations(range(4), 3) --> 012 013 023 123
pool = tuple(iterable)
n = len(pool)
if r > n:
return
indices = list(range(r))
yield tuple(pool[i] for i in indices)
while True:
for i in reversed(range(r)):
if indices[i] != i + n - r:
break
else:
return
indices[i] += 1
for j in range(i+1, r):
indices[j] = indices[j-1] + 1
yield tuple(pool[i] for i in indices)
combinations() 的代码可被改写为 permutations() 过滤后的子序列,(相对于元素在输入中的位置)元素不是有序的。
…
Leetcode题目
列表(9.125 vs 5)
9.回文数
判断一个整数是否是回文数。回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数。
输入: 121
输出: true
输入: -121
输出: false
解释: 从左向右读, 为 -121 。 从右向左读, 为 121- 。因此它不是一个回文数。
直接判断即可,如不考虑正负的情况下,则加绝对值判断
class Solution:
def isPalindrome(self, x: int) -> bool:
if str(x)==(str(x)[::-1]):
return True
else:
return False
125. 验证回文串
给定一个字符串,验证它是否是回文串,只考虑字母和数字字符,可以忽略字母的大小写。
输入: "A man, a plan, a canal: Panama"
输出: true
首先,分析题目得到,需要去除字符串中的空格,标点符号,只保留字母和数字,并统一大小写。可以引入isalnum() 方法检测字符串是否由字母和数字组成,引入lower()方法全部转成小写。
class Solution:
def isPalindrome(self, s: str) -> bool:
res = ''.join(e for e in s if e.isalnum()).lower()
return res==res[::-1]
5. 最长回文子串
输入: "babad"
输出: "bab"
注意: "aba" 也是一个有效答案。
待求解
迭代器
17. 电话号码的字母组合
给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。
给出数字到字母的映射与电话按键相同。注意 1 不对应任何字母。
输入:"23"
输出:["ad", "ae", "af", "bd", "be", "bf", "cd", "ce", "cf"].
从示例可以发现,字母组合和迭代器函数中的排列组合函数itertools.product(*iterables, repeat=1)实现效果相似,即输出输入数字对应字符串的笛卡尔积组合。仿照该函数实现。
class Solution:
def letterCombinations(self, digits: str) -> List[str]:
KEY = {'2': 'abc',
'3': 'def',
'4': 'ghi',
'5': 'jkl',
'6': 'mno',
'7': 'pqrs',
'8': 'tuv',
'9': 'wxyz'}
if digits == '':
return []
ans = ['']
for num in digits:
ans = [x + y for x in ans for y in KEY[num]]
return ans
216. 组合总和 III
找出所有相加之和为 n 的 k 个数的组合。组合中只允许含有 1 - 9 的正整数,并且每种组合中不存在重复的数字。
输入: k = 3, n = 9
输出: [[1,2,6], [1,3,5], [2,3,4]]
可使用迭代器中的conbinations函数获取k个数字的全排列,再筛选出其中和为n的组合。
class Solution:
def combinationSum3(self, k: int, n: int) -> List[List[int]]:
res = list(itertools.combinations('123456789', k))
ans = []
for i in range(len(res)):
sum = 0
for j in res[i]:
sum += int(j)
if sum == n:
ans.append(list(map(int, res[i])))
return ans