phase 5 part 5: cs algorithms, network-os, web-security topics with tested examples; all 43 stacks pass --strict

This commit is contained in:
Shikui Wang committed 2026-10-23 16:47:11 +08:00
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("全部自检通过")
@@ -0,0 +1,63 @@
import random
import pytest
from patterns import (LRUCache, edit_distance, longest_unique_substring, lower_bound, merge_intervals,
shortest_path, top_k_frequent, topo_order, two_sum)
def test_two_sum():
assert two_sum([3, 3], 6) == (0, 1)
assert two_sum([1, 2], 10) is None
@pytest.mark.parametrize("s,n", [("", 0), ("bbbb", 1), ("pwwkew", 3), ("abba", 2), ("你好你们好", 3)])
def test_longest_unique(s, n):
assert longest_unique_substring(s) == n
def test_lower_bound_matches_bisect():
import bisect
rng = random.Random(0)
for _ in range(200): # 与标准库对拍
arr = sorted(rng.randint(0, 20) for _ in range(rng.randint(0, 15)))
t = rng.randint(-1, 21)
assert lower_bound(arr, t) == bisect.bisect_left(arr, t)
def test_top_k():
assert top_k_frequent([], 3) == []
assert top_k_frequent(list("aaabbc"), 1) == ["a"]
def test_shortest_path_blocked():
assert shortest_path([[0, 1], [1, 0]], (0, 0), (1, 1)) == -1
assert shortest_path([[0]], (0, 0), (0, 0)) == 0
def test_topo_cycle_and_order():
assert topo_order({"a": ["b"], "b": ["a"]}) is None
order = topo_order({"app": ["db", "cache"], "cache": ["net"], "db": ["net"]})
assert order is not None
pos = {n: i for i, n in enumerate(order)}
assert pos["net"] < pos["db"] < pos["app"] and pos["net"] < pos["cache"] < pos["app"]
def test_edit_distance():
assert edit_distance("", "abc") == 3
assert edit_distance("退货申请", "退款申请") == 1
def test_lru():
c = LRUCache(2)
c.put("a", 1)
c.put("b", 2)
assert c.get("a") == 1 # a 变成最近使用
c.put("c", 3) # 淘汰 b
assert c.get("b") is None and c.get("a") == 1 and c.get("c") == 3
def test_merge_intervals():
assert merge_intervals([]) == []
assert merge_intervals([(1, 4), (4, 5)]) == [(1, 5)]
assert merge_intervals([(5, 6), (1, 2)]) == [(1, 2), (5, 6)]