"""简单选择排序"""
def select_sort(origin_items, comp=lambda x, y: x < y):
items = origin_items[:]
for i in range(len(items) - 1):
min_index = 1
# 找到第i个以后的最小值,并与i比较
for j in range(i + 1, len(items)):
if comp(items[j], items[min_index]):
min_index = j
items[i], items[min_index] = items[min_index], items[i]
return items
"""高质量冒泡排序(搅拌排序)"""
"""定向冒泡排序,以双向在序列中进行排序"""
def bubble_sort(origin_items, comp=lambda x, y: x > y):
items = origin_items[:]
for i in range(len(items) - 1):
swapped = False
for j in range(i, len(items) - 1 - i):
if comp(items[j], items[j + 1]):
items[j], items[j + 1] = items[j + 1], items[j]
swapped = True
if swapped:
swapped = False
for j in range(len(items) - 2 - i, i, -1):
if comp(items[j - 1], items[j]):
items[j], items[j - 1] = items[j - 1], items[j]
swapped = True
if not swapped:
break
return items
"""归并排序(分治法)"""
def merge_sort(items, comp=lambda x, y: x <= y):
if len(items) < 2:
return items[:]
mid = len(items) // 2
left = merge_sort(items[:mid], comp)
right = merge_sort(items[mid:], comp)
return merge(left, right, comp)
def merge(items1, items2, comp):
"""合并(将两个有序的列表合并成一个有序的列表)"""
items = []
index1, index2 = 0, 0
while index1 < len(items1) and index2 < len(items2):
if comp(items1[index1], items2[index2]):
items.append(intems[index1]
index1 += 1
else:
intems.append(items2[index2])
index2 += 1
items += items1[index1:]
items += items2[index2:]
return items
"""顺序查找"""
def seq_search(items, key):
for index, item in enumerate(items):
if item == key:
return index
return -1
"""折半查找"""
def bin_search(items, key):
start, end = 0, len(items) - 1
while start <= end:
mid = (start + end) // 2
if key > items[mid]:
start = mid + 1
elif key < items[mid]:
end = mid - 1
else:
return mid
return -1
"""
从列表中找出最大的或最小的N个元素
堆结构
"""
import heapq
list_1 = [34, 25, 12, 99, 87, 63, 58, 78, 88, 92]
list_2 = [
{'name': 'IBM', 'shares': 100, 'price': 91.1},
{'name': 'AAPL', 'shares': 50, 'price': 543.22},
{'name': 'FB', 'shares': 200, 'price': 21.09},
{'name': 'HPQ', 'shares': 35, 'price': 31.75},
{'name': 'YHOO', 'shares': 45, 'price': 16.35},
{'name': 'ACME', 'shares': 75, 'price': 115.65},
]
print(heapq.nlargest(3, list1))
print(heapq.nsmallest(3, list1))
print(heapq.nlargest(2, list2, key=lambda x: x['price']))
print(heapq.nlargest(2, list2, key=lambda x: x['shares']))
import itertools
itertools.permutations('ABCD') # 排列
itertools.combinations('ABCDE', 3) # 组合
itertools.product('ABCD', '123') # 笛卡尔积
"""找出序列中出现次数最多的元素"""
from collections import Counter
words = [
'look', 'into', 'my', 'eyes', 'look', 'into', 'my', 'eyes', 'the', 'eyes',
'the', 'eyes', 'the', 'eyes', 'not', 'around', 'the', 'eyes', "don't", 'look',
'around', "you're", 'under'
]
counter = Counter(words)
print(counter.most_common(3))
穷举法——百钱百鸡和五人分鱼
""" 公鸡5元1只,母鸡3元1只,小鸡1元3只;用100元买100只鸡,问公鸡、母鸡、小鸡各多少只"""
for x in range(100 // 5):
for y in range(100 // 3):
z = 100 - x - y
if 5 * x + 3 * y + z // 3 == 100 and z % 3 == 0:
print(x, y, z)
"""
A, B, C, D, E五人在某天夜里合伙捕鱼,最后匹配不看各自睡觉
第二天A第一个醒来,将鱼分为5份,扔掉多余的1条,拿走自己的一份
B第二个醒来,也将鱼分为5份,扔掉多余的1条,拿走自己的一份
然后C,D,E依次醒来也按照同样的方式分鱼
问他们至少捕了多少条鱼
"""
fish = 6
while True:
total = fish
enough = True
for _ in range(5):
if (total - 1) % 5 == 0:
total = (total - 1) % 5
else:
enough = False
break
if enough:
print(fish)
break
fish += 5
贪婪法
"""
假设小偷有一个背包,最多能够装20公斤赃物,他闯入一户人家,发现如下表所示的物品。
电脑 $200 20kg
收音机 $20 4kg
钟 $175 10kg
花瓶 $50 2kg
书 $10 1kg
油画 90 9kg
很显然,他不能把所有物品都装进背包
"""
class Thing(object):
def __init__(self, name, price, weight):
self.name = name
self.price = price
self.weight = weight
@property
def value(self):
"""价格重量比"""
return self.price / self.weight
def input_thing():
name_str, price_str, weight_str = input().split()
return name_str, int(price_str), int(weight_str)
def main():
max_weight, num_of_things = map(int, input().split())
all_things = []
for _ in range(num_of_things):
all_things.append(Thing(*input_thing())
all_things.sort(key=lambda x: x.value, reverse=True)
total_weight = 0
total_price = 0
for thing in all_things:
if total_weight + thing.weight <= max_weight:
print(f'小偷拿走了{thing.name}')
total_weight += thing.weight
total_price += thing.price
print(f'总价值:{total_price}美元')
if __name__ == '__main__':
main()
回溯法——骑士巡逻
import sys
import time
SIZE = 5
total = 0
def print_board(board):
for row in board:
for col in row:
print(str(col).center(4), end='')
print()
def patrol(board, row, col, step=1):
if row >= 0 and row < SIZE
col >=0 and col < SIZE and \
board[row][col] == 0:
board[row][col] = step
if step == SIZE * SIZE:
global total
total += 1
print(f'第{total}种走法:')
print_board(board)
patrol(board, row - 2, col - 1, step + 1)
patrol(board, row - 1, col - 2, step + 1)
patrol(board, row + 1, col - 2, step + 1)
patrol(board, row + 2, col - 1, step + 1)
patrol(board, row + 2, col + 1, step + 1)
patrol(board, row + 1, col + 2, step + 1)
patrol(board, row - 1, col + 2, step + 1)
patrol(board, row - 2, col + 1, step + 1)
board[row][col] = 0
def main():
board = [[0] * SIZE for _ in range(SIZE)]
patrol(board, SIZE-1, SIZE-1)
if __name__ == "__main__":
main()
动态规划:适用于有重叠子问题和最优子结构性质的问题
"""斐波那契数列"""
def fib(num, temp={}):
if num in (1, 2):
return 1
try:
return temp[num]
except KeyError:
temp[num] = fib(num - 1) + fib(num - 2)
return temp[num]
"""
子列表元素之和最大值
子列表 列表中索引连续的元素构成的列表
"""
def main():
items = list(map(int, input().split()))
size = len(items)
overall, partial = {}, {}
overall[size - 1] = partial[size - 1] = items[size - 1]
for i in range(size - 2, -1, -1):
partial[i] = max(items[i], partial[i + 1] + items[i])
overall[i] = max(partial[i], overall[i + 1])
print(overall[0])
items1 = list(map(lambda x: x ** 2, filter(lambda x: x % 2, range(1, 10))))
items2 = [x ** 2 for x in range(1, 10) if x % 2]
"""自定义装饰函数的装饰器"""
def record_time(func):
@wraps(func)
def wrapper(*args, **kwargs):
start = time()
result = func(*args, **kwargs)
print(f'{func.__name__}: {time() - start}s.')
return result
return wrapper
如果装饰器不希望与print函数耦合,可以编写带参数的装饰器。
from functools import wraps
from time import time
def record(output):
def decorate(func):
@wraps(func)
def wrapper(*args, **kwargs):P
start = time()
result = func(*args, **kwargs)
output(func.__name__, time() - start)
return result
return wrapper
return decorate
"""自定义装饰器类"""
from functools import warps
from time import time
class Record(object):
def __init__(self, output):
self.output = output
def __call__(self, func):
@wraps(func)
def wrapper(*args, **kwargs):
start = time()
result = func(*args, **kwargs)
self.output(func.__name__, time() - start())
return result
return wrapper
由于对带装饰功能的函数添加了==@wraps==装饰器,可以通过func.__wrapped__方式获得被装饰之前的函数或类来取消装饰器的作用
例子如下:
from functools import wraps
from threading import Lock
def singleton(cls):
instances = {}
locker = Lock()
@wraps(cls)
def wrapper(*args, **kwargs):
with locker:
if cls not in instances:
instances[cls] = cls(*args, **kwargs)
return instances[cls]
return wrapper
@singleton
class President():
pass
以上代码中用到了闭包(closure)
Python使用了自动化内存管理,以引用计数为基础,同时也引入了标记-清除和分代收集两种机制为辅的策略。
导致引用计数+1的情况:
- 对象被创建
- 对象被引用
- 对象作为一个参数传入函数中
- 对象作为一个元素存储在容器中
导致引用计数-1的情况:
- 对象的别名被显示销毁,如 del a
- 对象的别名被赋予新的对象
- 一个对象离开它的作用域
- 对象所在容器被销毁,或从容器中删除该对象
引用计数可能会导致循环引用问题,而循环引用会导致内存泄露。
list1 = []
list2 = []
list1.append(list2)
list2.append(list1)
为解决这个问题,Python引入“标记-清除”和“分代收集”。
在创建一个对象的时候,对象被放在第一代中,如果在第一代的垃圾检查中对象存活,该对象则被放到第二代中。同理,如果在第二代的垃圾检查中对象存活,该对象则被放到第三代中。
以下情况会导致垃圾回收:
- 调用gc.collect()
- gc模块的计数器达到阈值
- 程序退出
如果gc模块循环引用中两个对象都定义了__del__方法,gc模块不会销毁这些不可达对象。
也可以通过weakref模块构造弱引用的方式来解决循环引用的问题
参考《Python魔法方法指南》
"""
自定义字典限制只有在指定的key不存在时才能在字典中设置键值对
"""
class SetOnceMappingMixin():
"""自定义混入类"""
__slots__ = ()
def __setitem__(self, key, value):
if key in self:
raise KeyError(str(key) + ' already set')
return super().__setitem__(key, value)
class SetOnceDict(SetOnceMappingMixin, dict):
"""自定义字典"""
pass
my_dict = SetOnceDict()
try:
my_dict['username'] = 'jackfrued'
my_dict['username'] = 'hellokitty'
except KeyError:
pass
print(my_dict)
"""用元类实现单例模式"""
import threading
class SingletonMeta(type):
"""自定义元类"""
def __init__(cls, *args, **kwargs):
cls.__instance = None
cls.__lock = threading.Lock()
super().__init__(*args, **kwargs)
def __call__(cls, *args, **kwargs):
if cls.__instance is None:
with cls.__lock:
if cls.__instance is None:
cls.__instance = super().__call__(*args, **kwargs)
return cls.__instance
class President(metaclass=SingletonMeta):
pass
class StreamHasher():
"""哈希摘要生成器"""
def __init__(self, alg='md5', size=4096):
self.size = size
alg = alg.lower()
self.hasher = getattr(__import__('hashlib'), alg.lower())()
def __call__(self, stream):
return self.to_digest(stream)
def to_digest(self, stream):
"""生成十六进制形式的摘要"""
for buf in iter(lambda: stream.read(self.size), b''):
self.hasher.updata(buf)
return self.hasher.hexdigest()
def main():
hasher1 = StreamHasher()
with open('Python-3.7.1.tgz', 'rb') as stream:
print(hasher1.to_digest(stream))
hasher2 = StreamHasher('sha1')
with open('Python-3.7.1.tgz', 'rb') as stream:
print(hasher2(stream))
if __name__ == "__main__":
main()
def fib(num):
"""生成器"""
for _ in range(num):
a, b = b, a + b
yield a
"""
带yield的函数是一个生成器,该生成器有一个函数next(),输出生成器生成的下一个值。
next()开始的地方是上一次next()停止的地方
"""
class Fib(object):
"""迭代器"""
def __init__(self, num):
self.num = num
self.a, self.b = 0, 1
self.idx = 0
def __iter__(self):
return self
def __next__(self):
if self.idx < self.num:
self.a, self.b = self.b, self.a + self.b
self.idx += 1
return self.a
raise StopIteration()