phase 5 part 5: cs algorithms, network-os, web-security topics with tested examples; all 43 stacks pass --strict
This commit is contained in:
1 parent
f695bbd7cc
commit
691f738f5f
22 files changed
+1955
-37
No files matched your search
@@ -0,0 +1,142 @@
|
||||
"""面试高频算法模式(只用标准库)。每个函数注明时间 / 空间复杂度;`python patterns.py` 运行自检,test_patterns.py 是测试。"""
|
||||
from __future__ import annotations
|
||||
|
||||
import heapq
|
||||
from collections import Counter, OrderedDict, deque
|
||||
from typing import Hashable, Iterable
|
||||
|
||||
|
||||
# 1. 哈希表:两数之和 O(n) / O(n)
|
||||
def two_sum(nums: list[int], target: int) -> tuple[int, int] | None:
|
||||
seen: dict[int, int] = {}
|
||||
for i, x in enumerate(nums):
|
||||
if target - x in seen:
|
||||
return seen[target - x], i
|
||||
seen[x] = i
|
||||
return None
|
||||
|
||||
|
||||
# 2. 滑动窗口:无重复字符的最长子串 O(n) / O(字符集)
|
||||
def longest_unique_substring(s: str) -> int:
|
||||
last: dict[str, int] = {}
|
||||
left = best = 0
|
||||
for right, ch in enumerate(s):
|
||||
if last.get(ch, -1) >= left:
|
||||
left = last[ch] + 1 # 窗口左边界跳到重复字符的下一位
|
||||
last[ch] = right
|
||||
best = max(best, right - left + 1)
|
||||
return best
|
||||
|
||||
|
||||
# 3. 二分查找:第一个 >= target 的位置(lower_bound) O(log n) / O(1)
|
||||
def lower_bound(arr: list[int], target: int) -> int:
|
||||
lo, hi = 0, len(arr) # 左闭右开区间 [lo, hi)
|
||||
while lo < hi:
|
||||
mid = (lo + hi) // 2
|
||||
if arr[mid] < target:
|
||||
lo = mid + 1
|
||||
else:
|
||||
hi = mid
|
||||
return lo
|
||||
|
||||
|
||||
# 4. 堆:出现次数最多的 K 个(例如热门问题) O(n log k) / O(n)
|
||||
def top_k_frequent(items: Iterable[Hashable], k: int) -> list[Hashable]:
|
||||
counts = Counter(items)
|
||||
return [x for _, x in heapq.nlargest(k, ((c, x) for x, c in counts.items()))]
|
||||
|
||||
|
||||
# 5. BFS:网格最短路径(0 可走,1 障碍) O(行×列) / O(行×列)
|
||||
def shortest_path(grid: list[list[int]], start: tuple[int, int], end: tuple[int, int]) -> int:
|
||||
rows, cols = len(grid), len(grid[0])
|
||||
q = deque([(start, 0)])
|
||||
seen = {start}
|
||||
while q:
|
||||
(r, c), d = q.popleft()
|
||||
if (r, c) == end:
|
||||
return d
|
||||
for dr, dc in ((1, 0), (-1, 0), (0, 1), (0, -1)):
|
||||
nr, nc = r + dr, c + dc
|
||||
if 0 <= nr < rows and 0 <= nc < cols and grid[nr][nc] == 0 and (nr, nc) not in seen:
|
||||
seen.add((nr, nc))
|
||||
q.append(((nr, nc), d + 1))
|
||||
return -1
|
||||
|
||||
|
||||
# 6. DFS + 拓扑排序:任务依赖的执行顺序(有环返回 None) O(V+E)
|
||||
def topo_order(deps: dict[str, list[str]]) -> list[str] | None:
|
||||
"""deps[a] = [b, c] 表示 a 依赖 b 和 c(b、c 要先执行)。"""
|
||||
state: dict[str, int] = {} # 0/缺省 未访问,1 访问中,2 已完成
|
||||
order: list[str] = []
|
||||
|
||||
def visit(n: str) -> bool:
|
||||
if state.get(n) == 1:
|
||||
return False # 回到“访问中”的节点:有环
|
||||
if state.get(n) == 2:
|
||||
return True
|
||||
state[n] = 1
|
||||
for m in deps.get(n, []):
|
||||
if not visit(m):
|
||||
return False
|
||||
state[n] = 2
|
||||
order.append(n)
|
||||
return True
|
||||
|
||||
nodes = set(deps) | {m for ms in deps.values() for m in ms}
|
||||
for n in sorted(nodes):
|
||||
if not visit(n):
|
||||
return None
|
||||
return order
|
||||
|
||||
|
||||
# 7. 动态规划:编辑距离(文本相似度、纠错) O(mn) / O(n)
|
||||
def edit_distance(a: str, b: str) -> int:
|
||||
prev = list(range(len(b) + 1))
|
||||
for i in range(1, len(a) + 1):
|
||||
cur = [i] + [0] * len(b)
|
||||
for j in range(1, len(b) + 1):
|
||||
cur[j] = prev[j - 1] if a[i - 1] == b[j - 1] else 1 + min(prev[j - 1], prev[j], cur[j - 1])
|
||||
prev = cur
|
||||
return prev[-1]
|
||||
|
||||
|
||||
# 8. 设计题:LRU 缓存 get/put 均为 O(1)
|
||||
class LRUCache:
|
||||
def __init__(self, capacity: int):
|
||||
self.capacity = capacity
|
||||
self.data: OrderedDict[Hashable, object] = OrderedDict()
|
||||
|
||||
def get(self, key: Hashable) -> object | None:
|
||||
if key not in self.data:
|
||||
return None
|
||||
self.data.move_to_end(key) # 最近使用的移到末尾
|
||||
return self.data[key]
|
||||
|
||||
def put(self, key: Hashable, value: object) -> None:
|
||||
self.data[key] = value
|
||||
self.data.move_to_end(key)
|
||||
if len(self.data) > self.capacity:
|
||||
self.data.popitem(last=False) # 淘汰最久未使用的(头部)
|
||||
|
||||
|
||||
# 9. 区间合并:合并重叠的时间段(排班、会议室) O(n log n)
|
||||
def merge_intervals(intervals: list[tuple[int, int]]) -> list[tuple[int, int]]:
|
||||
out: list[tuple[int, int]] = []
|
||||
for s, e in sorted(intervals):
|
||||
if out and s <= out[-1][1]:
|
||||
out[-1] = (out[-1][0], max(out[-1][1], e))
|
||||
else:
|
||||
out.append((s, e))
|
||||
return out
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
assert two_sum([2, 7, 11, 15], 9) == (0, 1)
|
||||
assert longest_unique_substring("abcabcbb") == 3
|
||||
assert lower_bound([1, 3, 3, 5], 3) == 1
|
||||
assert top_k_frequent(["退货", "发票", "退货", "物流", "退货", "物流"], 2) == ["退货", "物流"]
|
||||
assert shortest_path([[0, 0, 0], [1, 1, 0], [0, 0, 0]], (0, 0), (2, 0)) == 6
|
||||
assert topo_order({"deploy": ["test"], "test": ["build"]}) == ["build", "test", "deploy"]
|
||||
assert edit_distance("kitten", "sitting") == 3
|
||||
assert merge_intervals([(1, 3), (2, 6), (8, 10)]) == [(1, 6), (8, 10)]
|
||||
print("全部自检通过")
|
||||
Reference in new issue
Block a user