chore: import zh skill code-mentor

This commit is contained in:
wehub-skill-sync
2026-07-13 21:36:32 +08:00
commit 6eb137bec1
16 changed files with 6163 additions and 0 deletions
+731
View File
@@ -0,0 +1,731 @@
# 常见算法模式
本参考涵盖编程面试和实际解决问题中最常用的算法模式。理解这些模式有助于你识别应对陌生问题时应采用哪种方法。
---
## 模式 1:双指针
**适用场景**:需要寻找数对、三元组或从两端处理元素的数组或字符串问题。
**何时使用**
- 在有序数组中寻找和为目标的数对
- 原地反转数组或字符串
- 从有序数组中移除重复项
- 盛最多水的容器类问题
**示例问题**
- 两数之和(有序数组)
- 验证回文串
- 盛最多水的容器
- 三数之和
**实现(Python**
```python
def two_sum_sorted(arr, target):
"""在有序数组中寻找两个数使其和等于目标值。"""
left, right = 0, len(arr) - 1
while left < right:
current_sum = arr[left] + arr[right]
if current_sum == target:
return [left, right]
elif current_sum < target:
left += 1 # 需要更大的和
else:
right -= 1 # 需要更小的和
return None # 未找到解
```
**实现(JavaScript**
```javascript
function twoSumSorted(arr, target) {
let left = 0, right = arr.length - 1;
while (left < right) {
const currentSum = arr[left] + arr[right];
if (currentSum === target) {
return [left, right];
} else if (currentSum < target) {
left++;
} else {
right--;
}
}
return null;
}
```
**时间复杂度**O(n) —— 单次遍历数组
**空间复杂度**O(1) —— 仅两个指针
---
## 模式 2:滑动窗口
**适用场景**:涉及子数组或子串的问题,需要寻找最优窗口大小或跟踪连续序列中的元素。
**何时使用**
- 大小为 k 的最大/最小子数组和
- 无重复字符的最长子串
- 在字符串中查找所有字母异位词
- 最小覆盖子串
**类型**
1. **固定大小窗口**:窗口大小恒定(例如大小为 k 的最大和)
2. **可变大小窗口**:窗口根据条件增大或缩小
**示例问题**
- 大小为 K 的最大子数组和
- 无重复字符的最长子串
- 最小覆盖子串
- 字符串中的排列
**实现(Python)—— 固定窗口**
```python
def max_sum_subarray(arr, k):
"""找出大小为 k 的任意子数组的最大和。"""
if len(arr) < k:
return None
# 计算第一个窗口的和
window_sum = sum(arr[:k])
max_sum = window_sum
# 滑动窗口
for i in range(k, len(arr)):
window_sum = window_sum - arr[i - k] + arr[i]
max_sum = max(max_sum, window_sum)
return max_sum
```
**实现(JavaScript)—— 可变窗口**
```javascript
function lengthOfLongestSubstring(s) {
const seen = new Set();
let left = 0;
let maxLength = 0;
for (let right = 0; right < s.length; right++) {
// 收缩窗口直到无重复
while (seen.has(s[right])) {
seen.delete(s[left]);
left++;
}
seen.add(s[right]);
maxLength = Math.max(maxLength, right - left + 1);
}
return maxLength;
}
```
**时间复杂度**:O(n) —— 每个元素最多被访问两次
**空间复杂度**:固定窗口为 O(k),可变窗口(含哈希集合)为 O(n)
---
## 模式 3:快慢指针(Floyd 环检测)
**适用场景**:链表问题,尤其是环检测和寻找中间元素。
**何时使用**
- 检测链表中的环
- 寻找链表的中点
- 寻找环的起点
- 判断一个数是否为快乐数
**示例问题**
- 环形链表
- 快乐数
- 寻找链表的中间节点
- 环起点检测
**实现(Python**
```python
class ListNode:
def __init__(self, val=0, next=None):
self.val = val
self.next = next
def has_cycle(head):
"""检测链表是否有环。"""
if not head:
return False
slow = fast = head
while fast and fast.next:
slow = slow.next # 移动 1 步
fast = fast.next.next # 移动 2 步
if slow == fast:
return True # 检测到环
return False
```
**时间复杂度**O(n)
**空间复杂度**O(1)
---
## 模式 4:合并区间
**适用场景**:处理重叠区间、调度或范围的问题。
**何时使用**
- 合并重叠区间
- 插入区间
- 会议室问题
- 区间交集
**示例问题**
- 合并区间
- 插入区间
- 会议室 II
- 区间列表的交集
**实现(Python**
```python
def merge_intervals(intervals):
"""合并重叠区间。"""
if not intervals:
return []
# 按开始时间排序
intervals.sort(key=lambda x: x[0])
merged = [intervals[0]]
for current in intervals[1:]:
last_merged = merged[-1]
if current[0] <= last_merged[1]:
# 重叠 —— 合并
merged[-1] = [last_merged[0], max(last_merged[1], current[1])]
else:
# 不重叠 —— 添加新区间
merged.append(current)
return merged
```
**时间复杂度**:O(n log n) —— 因排序导致
**空间复杂度**O(n) —— 输出空间
---
## 模式 5:循环排序
**适用场景**:数组中包含给定范围内(通常为 1 到 n)的数字的问题。
**何时使用**
- 查找缺失/重复的数字
- 查找所有缺失的数字
- 查找损坏数对
- 包含 1 到 n 数字的数组
**示例问题**
- 寻找缺失数字
- 寻找所有缺失数字
- 寻找重复数字
- 寻找损坏数对
**实现(Python**
```python
def cyclic_sort(nums):
"""对范围为 1 到 n 的数组进行排序。"""
i = 0
while i < len(nums):
correct_index = nums[i] - 1
if nums[i] != nums[correct_index]:
# 交换到正确位置
nums[i], nums[correct_index] = nums[correct_index], nums[i]
else:
i += 1
return nums
def find_missing_number(nums):
"""在 [0, n] 范围内查找缺失的数字。"""
n = len(nums)
i = 0
# 循环排序
while i < n:
correct_index = nums[i]
if nums[i] < n and nums[i] != nums[correct_index]:
nums[i], nums[correct_index] = nums[correct_index], nums[i]
else:
i += 1
# 查找缺失
for i in range(n):
if nums[i] != i:
return i
return n
```
**时间复杂度**O(n)
**空间复杂度**O(1)
---
## 模式 6:链表原地反转
**适用场景**:在不使用额外空间的情况下反转链表或链表的一部分。
**何时使用**
- 反转整个链表
- 反转从位置 m 到 n 的子链表
- 按 k 个一组反转
- 回文链表检测
**示例问题**
- 反转链表
- 反转链表 II
- K 个一组翻转链表
**实现(Python**
```python
def reverse_linked_list(head):
"""原地反转链表。"""
prev = None
current = head
while current:
next_node = current.next # 保存下一个节点
current.next = prev # 反转指针
prev = current # 向前移动 prev
current = next_node # 向前移动 current
return prev # 新的头节点
```
**实现(JavaScript**
```javascript
function reverseLinkedList(head) {
let prev = null;
let current = head;
while (current !== null) {
const nextNode = current.next;
current.next = prev;
prev = current;
current = nextNode;
}
return prev;
}
```
**时间复杂度**O(n)
**空间复杂度**O(1)
---
## 模式 7:树 BFS(广度优先搜索)
**适用场景**:树的层序遍历,查找层级特定信息。
**何时使用**
- 层序遍历
- 查找最小深度
- 锯齿形层序遍历
- 连接层序兄弟节点
- 树的右视图
**示例问题**
- 二叉树的层序遍历
- 二叉树的锯齿形遍历
- 二叉树的最小深度
- 连接层序兄弟节点
**实现(Python**
```python
from collections import deque
def level_order_traversal(root):
"""BFS 遍历,返回层级列表。"""
if not root:
return []
result = []
queue = deque([root])
while queue:
level_size = len(queue)
current_level = []
for _ in range(level_size):
node = queue.popleft()
current_level.append(node.val)
if node.left:
queue.append(node.left)
if node.right:
queue.append(node.right)
result.append(current_level)
return result
```
**时间复杂度**O(n)
**空间复杂度**O(n) —— 队列空间
---
## 模式 8:树 DFS(深度优先搜索)
**适用场景**:基于路径的树问题,递归树遍历。
**何时使用**
- 查找从根到叶的所有路径
- 路径数字之和
- 给定和的路径
- 统计和为某值的路径数
- 树的直径
**类型**
1. **前序遍历**:根 → 左 → 右
2. **中序遍历**:左 → 根 → 右
3. **后序遍历**:左 → 右 → 根
**示例问题**
- 二叉树路径
- 路径总和
- 求根到叶节点数字之和
- 二叉树的直径
**实现(Python**
```python
def has_path_sum(root, target_sum):
"""检查树是否存在根到叶路径,其节点和等于给定值。"""
if not root:
return False
# 叶节点 —— 检查和是否匹配
if not root.left and not root.right:
return root.val == target_sum
# 递归 DFS
remaining_sum = target_sum - root.val
return (has_path_sum(root.left, remaining_sum) or
has_path_sum(root.right, remaining_sum))
```
**时间复杂度**O(n)
**空间复杂度**:O(h),其中 h 为树高(递归栈)
---
## 模式 9:双堆
**适用场景**:需要查找中位数或将元素分为两半的问题。
**何时使用**
- 从数据流中找中位数
- 滑动窗口中位数
- IPO(最大化资本)
**结构**
- **最大堆**:存储较小的一半数字
- **最小堆**:存储较大的一半数字
- 中位数为最大堆的最大值或两堆堆顶的平均值
**实现(Python**
```python
import heapq
class MedianFinder:
def __init__(self):
self.max_heap = [] # 较小的一半(取反实现最大堆)
self.min_heap = [] # 较大的一半
def add_num(self, num):
# 先加入最大堆
heapq.heappush(self.max_heap, -num)
# 平衡:将最大堆的最大值移到最小堆
heapq.heappush(self.min_heap, -heapq.heappop(self.max_heap))
# 确保最大堆元素个数等于或多于最小堆
if len(self.max_heap) < len(self.min_heap):
heapq.heappush(self.max_heap, -heapq.heappop(self.min_heap))
def find_median(self):
if len(self.max_heap) > len(self.min_heap):
return -self.max_heap[0]
return (-self.max_heap[0] + self.min_heap[0]) / 2
```
**时间复杂度**:插入 O(log n),查找中位数 O(1)
**空间复杂度**O(n)
---
## 模式 10:子集(回溯)
**适用场景**:需要生成所有组合、排列或子集的问题。
**何时使用**
- 生成所有子集/幂集
- 排列
- 组合
- 字母大小写全排列
**示例问题**
- 子集
- 排列
- 组合
- 括号生成
**实现(Python**
```python
def subsets(nums):
"""使用回溯生成所有子集。"""
result = []
def backtrack(start, current):
# 添加当前子集
result.append(current[:])
# 探索后续元素
for i in range(start, len(nums)):
current.append(nums[i])
backtrack(i + 1, current)
current.pop() # 回溯
backtrack(0, [])
return result
```
**时间复杂度**O(2^n) —— 指数级
**空间复杂度**O(n) —— 递归深度
---
## 模式 11:二分查找
**适用场景**:在有序数组或搜索空间中查找,寻找边界。
**何时使用**
- 在有序数组中查找
- 查找第一个/最后一个出现位置
- 在旋转有序数组中查找
- 寻找峰值元素
- 在二维矩阵中查找
**模板**
```python
def binary_search(arr, target):
"""标准二分查找。"""
left, right = 0, len(arr) - 1
while left <= right:
mid = left + (right - left) // 2 # 避免溢出
if arr[mid] == target:
return mid
elif arr[mid] < target:
left = mid + 1
else:
right = mid - 1
return -1 # 未找到
```
**时间复杂度**O(log n)
**空间复杂度**O(1)
---
## 模式 12Top K 元素
**适用场景**:查找 k 个最大/最小元素,k 个最频繁元素。
**何时使用**
- K 个最大/最小元素
- K 个最近的点
- K 个最频繁的元素
- 按频率对字符排序
**实现(Python**
```python
import heapq
def k_largest_elements(nums, k):
"""使用最小堆查找 k 个最大元素。"""
# 维护大小为 k 的最小堆
min_heap = []
for num in nums:
heapq.heappush(min_heap, num)
if len(min_heap) > k:
heapq.heappop(min_heap)
return min_heap
```
**时间复杂度**O(n log k)
**空间复杂度**O(k)
---
## 模式 13:改进版二分查找
**适用场景**:针对复杂场景的二分查找变体。
**何时使用**
- 在旋转有序数组中查找
- 在旋转有序数组中查找最小值
- 在无限有序数组中查找
- 查找范围(第一个和最后一个位置)
**实现(Python**
```python
def search_rotated_array(nums, target):
"""在旋转有序数组中查找目标值。"""
left, right = 0, len(nums) - 1
while left <= right:
mid = left + (right - left) // 2
if nums[mid] == target:
return mid
# 判断哪一半是有序的
if nums[left] <= nums[mid]: # 左半有序
if nums[left] <= target < nums[mid]:
right = mid - 1
else:
left = mid + 1
else: # 右半有序
if nums[mid] < target <= nums[right]:
left = mid + 1
else:
right = mid - 1
return -1
```
---
## 模式 14:动态规划(自顶向下)
**适用场景**:具有重叠子问题的最优化问题。
**何时使用**
- 斐波那契数列、爬楼梯
- 打家劫舍
- 零钱兑换
- 最长公共子序列
- 0/1 背包
**模板(记忆化)**
```python
def fibonacci(n, memo={}):
"""使用记忆化计算第 n 个斐波那契数。"""
if n in memo:
return memo[n]
if n <= 1:
return n
memo[n] = fibonacci(n - 1, memo) + fibonacci(n - 2, memo)
return memo[n]
```
**时间复杂度**:取决于具体问题(通常为 O(n) 或 O(n²))
**空间复杂度**O(n) —— 记忆化加递归栈
---
## 模式 15:动态规划(自底向上)
**适用场景**:与自顶向下相同,但采用迭代方式(通常更高效)。
**模板(表格法)**
```python
def fibonacci_dp(n):
"""使用自底向上 DP 计算第 n 个斐波那契数。"""
if n <= 1:
return n
dp = [0] * (n + 1)
dp[1] = 1
for i in range(2, n + 1):
dp[i] = dp[i - 1] + dp[i - 2]
return dp[n]
```
**空间优化**(以斐波那契为例):
```python
def fibonacci_optimized(n):
"""空间优化的斐波那契计算。"""
if n <= 1:
return n
prev2, prev1 = 0, 1
for _ in range(2, n + 1):
current = prev1 + prev2
prev2, prev1 = prev1, current
return prev1
```
---
## 如何选择正确的模式
问自己以下几个问题:
1. **输入结构是什么?**
- 有序数组 → 二分查找、双指针
- 链表 → 快慢指针、原地反转
- 树 → BFS、DFS
- 区间 → 合并区间
2. **我在寻找什么?**
- 子数组/子串 → 滑动窗口
- 数对/三元组 → 双指针
- 所有组合 → 回溯
- 带选择的最优解 → 动态规划
- Top k 个元素 → 堆
3. **是否存在约束条件?**
- 数字范围在 [1, n] → 循环排序
- 需要中位数 → 双堆
- 原地修改 → 双指针、循环排序
4. **时间复杂度要求是什么?**
- O(log n) → 二分查找
- O(n) → 双指针、滑动窗口、哈希表
- O(n log n) → 排序、堆
- 可以接受指数级? → 回溯、递归
---
**练习策略**
1. 每次掌握一种模式
2. 每个模式解决 5-10 道题
3. 在新问题中识别模式
4. 组合模式解决复杂问题
**常见模式组合**
- 双指针 + 滑动窗口
- 二分查找 + DFS
- 动态规划 + 记忆化
- 回溯 + 剪枝
+843
View File
@@ -0,0 +1,843 @@
# Clean Code Principles
# 整洁代码原则
## Core Principles
## 核心原则
### 1. Meaningful Names
### 1. 有意义的命名
**Variables**:
**变量**
```python
# BAD
d = 10 # What is 'd'?
t = time.time()
# GOOD
elapsed_days = 10
current_timestamp = time.time()
```
**Functions**:
**函数**
```python
# BAD
def process(data):
pass
# GOOD
def calculate_user_average_score(user_scores):
pass
```
**Classes**:
**类**
```python
# BAD
class Data:
pass
# GOOD
class CustomerOrderProcessor:
pass
```
**Boolean variables** - use predicates:
**布尔变量**——使用谓词:
```python
# BAD
flag = True
status = False
# GOOD
is_active = True
has_permission = False
can_edit = True
should_retry = False
```
---
### 2. Functions Should Do One Thing
### 2. 函数应该只做一件事
**BAD** - Multiple responsibilities:
**反面示例**——多重职责:
```python
def process_user_data(user):
# Validate
if not user.email:
raise ValueError("Email required")
# Transform
user.name = user.name.upper()
# Save to database
db.save(user)
# Send email
email_service.send_welcome(user.email)
# Log
logger.info(f"User processed: {user.id}")
```
**GOOD** - Single responsibility:
**正面示例**——单一职责:
```python
def validate_user(user):
if not user.email:
raise ValueError("Email required")
def normalize_user_data(user):
user.name = user.name.upper()
return user
def save_user(user):
db.save(user)
def send_welcome_email(email):
email_service.send_welcome(email)
def process_user_data(user):
validate_user(user)
user = normalize_user_data(user)
save_user(user)
send_welcome_email(user.email)
logger.info(f"User processed: {user.id}")
```
---
### 3. Keep Functions Small
### 3. 保持函数短小
**Guideline**: Aim for 10-20 lines per function.
**指导原则**:每个函数控制在 1020 行。
**BAD** - 100+ line function:
**反面示例**——超过 100 行的函数:
```python
def generate_report(users):
# 100 lines of mixed logic
# Filtering, sorting, formatting, calculations, file I/O
pass
```
**GOOD** - Extracted functions:
**正面示例**——提取后的函数:
```python
def generate_report(users):
active_users = filter_active_users(users)
sorted_users = sort_by_activity(active_users)
report_data = calculate_statistics(sorted_users)
formatted_report = format_report(report_data)
save_report(formatted_report)
def filter_active_users(users):
return [u for u in users if u.is_active]
def sort_by_activity(users):
return sorted(users, key=lambda u: u.activity_score, reverse=True)
```
---
### 4. DRY (Don't Repeat Yourself)
### 4. DRY(不要重复自己)
**BAD** - Duplication:
**反面示例**——重复代码:
```python
def calculate_student_grade(math_score, science_score):
if math_score >= 90:
math_grade = 'A'
elif math_score >= 80:
math_grade = 'B'
elif math_score >= 70:
math_grade = 'C'
else:
math_grade = 'F'
if science_score >= 90:
science_grade = 'A'
elif science_score >= 80:
science_grade = 'B'
elif science_score >= 70:
science_grade = 'C'
else:
science_grade = 'F'
return math_grade, science_grade
```
**GOOD** - Extract common logic:
**正面示例**——提取公共逻辑:
```python
def score_to_grade(score):
if score >= 90:
return 'A'
elif score >= 80:
return 'B'
elif score >= 70:
return 'C'
return 'F'
def calculate_student_grade(math_score, science_score):
return score_to_grade(math_score), score_to_grade(science_score)
```
---
### 5. Avoid Magic Numbers
### 5. 避免魔数
**BAD**:
**反面示例**
```python
if age > 18:
can_vote = True
if len(password) < 8:
raise ValueError("Password too short")
```
**GOOD**:
**正面示例**
```python
VOTING_AGE = 18
MIN_PASSWORD_LENGTH = 8
if age > VOTING_AGE:
can_vote = True
if len(password) < MIN_PASSWORD_LENGTH:
raise ValueError(f"Password must be at least {MIN_PASSWORD_LENGTH} characters")
```
---
### 6. Error Handling
### 6. 错误处理
**BAD** - Bare except, silent failures:
**反面示例**——裸 except、静默失败:
```python
try:
result = risky_operation()
except:
pass # What went wrong?
```
**GOOD** - Specific exceptions, informative messages:
**正面示例**——具体异常、信息性消息:
```python
try:
result = risky_operation()
except ValueError as e:
logger.error(f"Invalid value: {e}")
raise
except ConnectionError as e:
logger.error(f"Connection failed: {e}")
# Retry or fallback logic
```
---
### 7. Use Early Returns (Guard Clauses)
### 7. 使用提前返回(卫语句)
**BAD** - Nested conditions:
**反面示例**——嵌套条件:
```python
def process_order(order):
if order is not None:
if order.is_valid():
if order.total > 0:
if order.customer.has_credit():
# Process order
return True
return False
```
**GOOD** - Early returns:
**正面示例**——提前返回:
```python
def process_order(order):
if order is None:
return False
if not order.is_valid():
return False
if order.total <= 0:
return False
if not order.customer.has_credit():
return False
# Process order
return True
```
---
### 8. Comment Why, Not What
### 8. 注释说明「为什么」,而非「是什么」
**BAD** - Obvious comments:
**反面示例**——显而易见的注释:
```python
# Increment i by 1
i += 1
# Loop through users
for user in users:
pass
```
**GOOD** - Explain non-obvious reasoning:
**正面示例**——解释非显而易见的理由:
```python
# Use binary search because list is always sorted
# and can contain millions of items
index = binary_search(sorted_list, target)
# Cache for 5 minutes to reduce database load
# during peak hours (based on profiling data)
@cache(ttl=300)
def get_popular_products():
pass
```
---
### 9. Keep Indentation Shallow
### 9. 保持缩进深度较浅
**BAD** - Deep nesting:
**反面示例**——深层嵌套:
```python
def process_data(items):
for item in items:
if item.is_valid():
if item.quantity > 0:
if item.price > 0:
if item.in_stock:
# Process
pass
```
**GOOD** - Use early returns, extraction:
**正面示例**——使用提前返回和提取:
```python
def process_data(items):
for item in items:
if not should_process_item(item):
continue
process_item(item)
def should_process_item(item):
return (item.is_valid() and
item.quantity > 0 and
item.price > 0 and
item.in_stock)
```
---
### 10. Consistent Formatting
### 10. 一致的格式化
**Use a formatter**: Black (Python), Prettier (JavaScript), gofmt (Go)
**使用格式化工具**Black (Python)、Prettier (JavaScript)、gofmt (Go)
**Consistency matters**:
**一致性很重要**
```python
# Pick one style and stick to it
# 选择一种风格并坚持使用
# Style 1
def foo(x, y, z):
return x + y + z
# Style 2
def foo(
x,
y,
z
):
return x + y + z
# Don't mix them randomly in the same file!
# 不要在同一个文件中随意混用!
```
---
## SOLID Principles
## SOLID 原则
### S - Single Responsibility Principle
### S——单一职责原则
**A class should have one, and only one, reason to change.**
**一个类应该只有一个、且仅有一个变更理由。**
**BAD**:
**反面示例**
```python
class User:
def __init__(self, name, email):
self.name = name
self.email = email
def save(self):
# Database logic
db.execute(f"INSERT INTO users...")
def send_email(self, message):
# Email logic
smtp.send(self.email, message)
```
**GOOD**:
**正面示例**
```python
class User:
def __init__(self, name, email):
self.name = name
self.email = email
class UserRepository:
def save(self, user):
db.execute(f"INSERT INTO users...")
class EmailService:
def send_email(self, email, message):
smtp.send(email, message)
```
---
### O - Open/Closed Principle
### O——开闭原则
**Open for extension, closed for modification.**
**对扩展开放,对修改关闭。**
**BAD**:
**反面示例**
```python
class PaymentProcessor:
def process(self, payment_type, amount):
if payment_type == "credit_card":
# Credit card processing
pass
elif payment_type == "paypal":
# PayPal processing
pass
# Adding new type requires modifying this function!
```
**GOOD**:
**正面示例**
```python
from abc import ABC, abstractmethod
class PaymentMethod(ABC):
@abstractmethod
def process(self, amount):
pass
class CreditCardPayment(PaymentMethod):
def process(self, amount):
# Credit card processing
pass
class PayPalPayment(PaymentMethod):
def process(self, amount):
# PayPal processing
pass
class PaymentProcessor:
def process(self, payment_method: PaymentMethod, amount):
payment_method.process(amount)
```
---
### L - Liskov Substitution Principle
### L——里氏替换原则
**Subclasses should be substitutable for their base classes.**
**子类应该可以替换其基类。**
**BAD**:
**反面示例**
```python
class Bird:
def fly(self):
print("Flying")
class Penguin(Bird):
def fly(self):
raise Exception("Penguins can't fly!")
```
**GOOD**:
**正面示例**
```python
class Bird:
def move(self):
pass
class FlyingBird(Bird):
def move(self):
self.fly()
def fly(self):
print("Flying")
class Penguin(Bird):
def move(self):
self.swim()
def swim(self):
print("Swimming")
```
---
### I - Interface Segregation Principle
### I——接口隔离原则
**Clients should not depend on interfaces they don't use.**
**客户端不应该依赖它们不使用的方法。**
**BAD**:
**反面示例**
```python
class Worker(ABC):
@abstractmethod
def work(self):
pass
@abstractmethod
def eat(self):
pass
class Robot(Worker):
def work(self):
print("Working")
def eat(self):
# Robots don't eat!
raise NotImplementedError
```
**GOOD**:
**正面示例**
```python
class Workable(ABC):
@abstractmethod
def work(self):
pass
class Eatable(ABC):
@abstractmethod
def eat(self):
pass
class Human(Workable, Eatable):
def work(self):
print("Working")
def eat(self):
print("Eating")
class Robot(Workable):
def work(self):
print("Working")
```
---
### D - Dependency Inversion Principle
### D——依赖倒置原则
**Depend on abstractions, not concretions.**
**依赖抽象,而非具体实现。**
**BAD**:
**反面示例**
```python
class MySQLDatabase:
def save(self, data):
pass
class UserService:
def __init__(self):
self.db = MySQLDatabase() # Tightly coupled
def save_user(self, user):
self.db.save(user)
```
**GOOD**:
**正面示例**
```python
class Database(ABC):
@abstractmethod
def save(self, data):
pass
class MySQLDatabase(Database):
def save(self, data):
pass
class PostgresDatabase(Database):
def save(self, data):
pass
class UserService:
def __init__(self, database: Database):
self.db = database # Depends on abstraction
def save_user(self, user):
self.db.save(user)
```
---
## Code Smells to Avoid
## 需要避免的代码坏味
### 1. Long Parameter List
### 1. 过长的参数列表
```python
# BAD
def create_user(name, email, phone, address, city, state, zip, country):
pass
# GOOD
class UserData:
def __init__(self, name, email, contact_info, address):
pass
def create_user(user_data: UserData):
pass
```
### 2. Primitive Obsession
### 2. 基本类型偏执
```python
# BAD
def calculate_shipping(width, height, depth, weight):
pass
# GOOD
class Dimensions:
def __init__(self, width, height, depth):
self.width = width
self.height = height
self.depth = depth
class Package:
def __init__(self, dimensions, weight):
self.dimensions = dimensions
self.weight = weight
def calculate_shipping(package: Package):
pass
```
### 3. Feature Envy
### 3. 依恋情结
```python
# BAD - Method in class A uses mostly data from class B
class Order:
def calculate_total(self, customer):
discount = customer.discount_rate
points = customer.loyalty_points
# Uses customer data extensively
pass
# GOOD - Move method to class B
class Customer:
def calculate_order_discount(self, order):
discount = self.discount_rate
points = self.loyalty_points
# Uses own data
pass
```
---
## Testing Best Practices
## 测试最佳实践
### 1. AAA Pattern (Arrange-Act-Assert)
### 1. AAA 模式(Arrange-Act-Assert
```python
def test_user_creation():
# Arrange
name = "Alice"
email = "alice@example.com"
# Act
user = User(name, email)
# Assert
assert user.name == name
assert user.email == email
```
### 2. One Assertion Per Test (guideline)
### 2. 每个测试一个断言(指导原则)
```python
# AVOID multiple unrelated assertions
def test_user():
user = User("Alice", "alice@example.com")
assert user.name == "Alice"
assert user.email == "alice@example.com"
assert user.is_valid()
assert user.created_at is not None
# PREFER focused tests
def test_user_name():
user = User("Alice", "alice@example.com")
assert user.name == "Alice"
def test_user_email():
user = User("Alice", "alice@example.com")
assert user.email == "alice@example.com"
```
### 3. Test Names Should Be Descriptive
### 3. 测试名称应具有描述性
```python
# BAD
def test_user():
pass
# GOOD
def test_user_creation_with_valid_email_succeeds():
pass
def test_user_creation_with_invalid_email_raises_error():
pass
```
---
## Refactoring Checklist
## 重构检查清单
When you see code that needs improvement:
当你看到需要改进的代码时:
1. **Is it tested?** If not, write tests first
2. **One change at a time** - Refactor incrementally
3. **Run tests after each change** - Ensure nothing breaks
4. **Commit frequently** - Small, focused commits
5. **Don't change behavior** - Refactoring should preserve functionality
1. **有测试吗?** 如果没有,先编写测试
2. **一次只改一处**——增量式重构
3. **每次修改后运行测试**——确保没有破坏任何功能
4. **频繁提交**——小而专注的提交
5. **不改变行为**——重构应保留原有功能
---
## Key Takeaways
## 关键要点
1. **Names matter** - Spend time choosing good names
2. **Functions should be small** - Aim for 10-20 lines
3. **One responsibility** - Each function/class does one thing well
4. **DRY** - Don't repeat yourself
5. **SOLID** - Follow the five SOLID principles
6. **Early returns** - Reduce nesting with guard clauses
7. **Comment why** - Not what (code shows what)
8. **Test** - Write tests, refactor with confidence
1. **命名很重要**——花时间选择好的名称
2. **函数应该短小**——目标是 1020 行
3. **单一职责**——每个函数/类做好一件事
4. **DRY**——不要重复自己
5. **SOLID**——遵循五大 SOLID 原则
6. **提前返回**——使用卫语句减少嵌套
7. **注释说明「为什么」**——而非「是什么」(代码本身就展示了是什么)
8. **测试**——编写测试,自信重构
**Remember**: Clean code is not about perfection—it's about making code easier to read, maintain, and extend!
**记住**:整洁代码不在于追求完美——而在于让代码更易读、更易维护、更易扩展!
@@ -0,0 +1,468 @@
# 数组与字符串参考
## 数组
### 核心概念
**数组(array** 是存储在连续内存位置上的元素集合。数组提供 O(1) 的随机访问,但插入/删除操作(末尾除外)为 O(n)。
**关键属性**
- 固定或动态大小(取决于语言)
- 同质元素(相同类型)
- 多数语言中从零开始索引
- 连续内存分配
### 常见操作
| 操作 | 时间复杂度 | 说明 |
|-----------|----------------|-------|
| 访问 | O(1) | 直接索引查找 |
| 搜索 | O(n) | 若已排序则 O(log n) + 二分查找 |
| 插入(末尾) | O(1) 均摊 | 可能触发扩容 |
| 插入(任意位置) | O(n) | 移动元素 |
| 删除(末尾) | O(1) | Pop 操作 |
| 删除(任意位置) | O(n) | 移动元素 |
### Python 实现
```python
# Array/List operations
arr = [1, 2, 3, 4, 5]
# Access
element = arr[2] # O(1)
# Search
index = arr.index(3) # O(n)
exists = 3 in arr # O(n)
# Insert
arr.append(6) # O(1) at end
arr.insert(2, 10) # O(n) at arbitrary position
# Delete
arr.pop() # O(1) from end
arr.pop(2) # O(n) from arbitrary position
arr.remove(10) # O(n) - finds and removes
# Slicing
subarray = arr[1:4] # O(k) where k is slice size
# Common patterns
reversed_arr = arr[::-1]
sorted_arr = sorted(arr) # O(n log n)
```
### JavaScript 实现
```javascript
// Array operations
const arr = [1, 2, 3, 4, 5];
// Access
const element = arr[2]; // O(1)
// Search
const index = arr.indexOf(3); // O(n)
const exists = arr.includes(3); // O(n)
// Insert
arr.push(6); // O(1) at end
arr.splice(2, 0, 10); // O(n) at arbitrary position
// Delete
arr.pop(); // O(1) from end
arr.splice(2, 1); // O(n) from arbitrary position
// Slicing
const subarray = arr.slice(1, 4); // O(k)
// Common patterns
const reversedArr = arr.reverse();
const sortedArr = arr.sort((a, b) => a - b); // O(n log n)
```
---
## 字符串
### 核心概念
**字符串(string** 是字符序列。在大多数语言中,字符串是不可变的(Python、Java),或被视为字符数组(C++,JavaScript 在某些情况下允许修改)。
**关键属性**
- 在 Python、Java、JavaScript(基本类型)中不可变
- 在 C++ 中是字符数组
- 需考虑 UTF-8/UTF-16 编码
- 拼接操作可能代价高昂
### 常见操作
| 操作 | 时间复杂度 | 说明 |
|-----------|----------------|-------|
| 访问 | O(1) | 直接索引查找 |
| 拼接 | O(n + m) | 若不可变则创建新字符串 |
| 子串 | O(k) | k = 子串长度 |
| 搜索 | O(n * m) | 朴素算法;使用 KMP 为 O(n + m) |
| 替换 | O(n) | 不可变语言中创建新字符串 |
### Python 实现
```python
s = "hello world"
# Access
char = s[0] # O(1)
# Slicing
substring = s[0:5] # O(k)
substring = s[::-1] # Reverse O(n)
# Search
index = s.find("world") # O(n), returns -1 if not found
index = s.index("world") # O(n), raises error if not found
exists = "world" in s # O(n)
# Modification (creates new string)
s_upper = s.upper()
s_lower = s.lower()
s_replaced = s.replace("world", "python")
# Split and join
words = s.split() # O(n)
joined = " ".join(words) # O(n)
# Common patterns
is_alpha = s.isalpha()
is_digit = s.isdigit()
stripped = s.strip() # Remove whitespace
```
### JavaScript 实现
```javascript
let s = "hello world";
// Access
const char = s[0]; // O(1)
// Slicing
const substring = s.slice(0, 5); // O(k)
const reversed = s.split('').reverse().join(''); // O(n)
// Search
const index = s.indexOf("world"); // O(n), returns -1 if not found
const exists = s.includes("world"); // O(n)
// Modification (creates new string)
const sUpper = s.toUpperCase();
const sLower = s.toLowerCase();
const sReplaced = s.replace("world", "javascript");
// Split and join
const words = s.split(' '); // O(n)
const joined = words.join(' '); // O(n)
// Common methods
const trimmed = s.trim();
const startsWithHello = s.startsWith("hello");
const endsWithWorld = s.endsWith("world");
```
---
## 常见数组/字符串模式
### 1. 双指针
**问题**:检查字符串是否为回文
```python
def is_palindrome(s):
left, right = 0, len(s) - 1
while left < right:
if s[left] != s[right]:
return False
left += 1
right -= 1
return True
```
### 2. 滑动窗口
**问题**:大小为 k 的最大子数组和
```python
def max_sum_subarray(arr, k):
if len(arr) < k:
return None
window_sum = sum(arr[:k])
max_sum = window_sum
for i in range(k, len(arr)):
window_sum = window_sum - arr[i - k] + arr[i]
max_sum = max(max_sum, window_sum)
return max_sum
```
### 3. 前缀和
**问题**:区间和查询
```python
class RangeSumQuery:
def __init__(self, nums):
self.prefix = [0]
for num in nums:
self.prefix.append(self.prefix[-1] + num)
def sum_range(self, left, right):
return self.prefix[right + 1] - self.prefix[left]
```
### 4. 哈希表统计频率
**问题**:字符串中第一个不重复的字符
```python
def first_unique_char(s):
from collections import Counter
freq = Counter(s)
for i, char in enumerate(s):
if freq[char] == 1:
return i
return -1
```
### 5. 字符串构建器(性能优化)
**问题**:高效字符串拼接
```python
# BAD: O(n²) due to immutability
result = ""
for i in range(n):
result += str(i) # Creates new string each time
# GOOD: O(n) using list
result = []
for i in range(n):
result.append(str(i))
final_result = "".join(result)
```
---
## 进阶技巧
### 1. Kadane 算法(最大子数组和)
```python
def max_subarray_sum(nums):
"""Find maximum sum of contiguous subarray."""
max_current = max_global = nums[0]
for i in range(1, len(nums)):
max_current = max(nums[i], max_current + nums[i])
max_global = max(max_global, max_current)
return max_global
```
**时间复杂度**O(n)**空间复杂度**O(1)
### 2. KMP 字符串匹配
```python
def kmp_search(text, pattern):
"""Knuth-Morris-Pratt string matching."""
def compute_lps(pattern):
lps = [0] * len(pattern)
length = 0
i = 1
while i < len(pattern):
if pattern[i] == pattern[length]:
length += 1
lps[i] = length
i += 1
else:
if length != 0:
length = lps[length - 1]
else:
lps[i] = 0
i += 1
return lps
lps = compute_lps(pattern)
i = j = 0
while i < len(text):
if pattern[j] == text[i]:
i += 1
j += 1
if j == len(pattern):
return i - j # Pattern found
elif i < len(text) and pattern[j] != text[i]:
if j != 0:
j = lps[j - 1]
else:
i += 1
return -1 # Not found
```
**时间复杂度**O(n + m)**空间复杂度**O(m)
### 3. Rabin-Karp(滚动哈希)
```python
def rabin_karp(text, pattern):
"""Rolling hash string matching."""
d = 256 # Number of characters
q = 101 # Prime number
m = len(pattern)
n = len(text)
p = 0 # Hash value for pattern
t = 0 # Hash value for text
h = 1
# Calculate h = pow(d, m-1) % q
for i in range(m - 1):
h = (h * d) % q
# Calculate initial hash values
for i in range(m):
p = (d * p + ord(pattern[i])) % q
t = (d * t + ord(text[i])) % q
# Slide pattern over text
for i in range(n - m + 1):
if p == t:
# Check characters one by one
if text[i:i + m] == pattern:
return i
# Calculate hash for next window
if i < n - m:
t = (d * (t - ord(text[i]) * h) + ord(text[i + m])) % q
if t < 0:
t += q
return -1
```
**平均时间复杂度**O(n + m)**最坏情况**O(n * m)
---
## 常见陷阱与最佳实践
### 陷阱 1:差一错误
```python
# WRONG
for i in range(len(arr) - 1): # Misses last element
print(arr[i])
# CORRECT
for i in range(len(arr)):
print(arr[i])
```
### 陷阱 2:遍历时修改
```python
# WRONG
for item in arr:
if item % 2 == 0:
arr.remove(item) # Can skip elements
# CORRECT
arr = [item for item in arr if item % 2 != 0]
# Or iterate backwards
for i in range(len(arr) - 1, -1, -1):
if arr[i] % 2 == 0:
arr.pop(i)
```
### 陷阱 3:循环中拼接字符串
```python
# INEFFICIENT: O(n²)
result = ""
for i in range(n):
result += str(i)
# EFFICIENT: O(n)
result = "".join(str(i) for i in range(n))
```
### 最佳实践 1:使用内置函数
```python
# Manual max finding
max_val = arr[0]
for val in arr:
if val > max_val:
max_val = val
# Better
max_val = max(arr)
```
### 最佳实践 2:列表推导式
```python
# Traditional loop
squares = []
for x in range(10):
squares.append(x ** 2)
# List comprehension (more Pythonic)
squares = [x ** 2 for x in range(10)]
```
### 最佳实践 3:使用 Enumerate 获取索引与值
```python
# Manual indexing
for i in range(len(arr)):
print(f"Index {i}: {arr[i]}")
# Better
for i, val in enumerate(arr):
print(f"Index {i}: {val}")
```
---
## 面试问题检查清单
在解决数组/字符串问题时:
1. **明确约束条件**
- 数组大小限制?
- 数组能否为空?
- 取值范围?
- 是否允许原地修改?
2. **考虑边界情况**
- 空数组/空字符串
- 单个元素
- 所有元素相同
- 已排序
- 负数(针对数组)
3. **选择方法**
- 先暴力求解(验证逻辑)
- 优化(双指针、哈希表、滑动窗口)
- 考虑时间/空间权衡
4. **用示例测试**
- 常规情况
- 边界情况
- 大量输入
5. **分析复杂度**
- 时间复杂度
- 空间复杂度
- 能否进一步优化?
+683
View File
@@ -0,0 +1,683 @@
# 树与图参考
## 二叉树
### 核心概念
**二叉树**是一种层次化数据结构,每个节点最多有两个子节点(左子节点与右子节点)。
**关键属性**
- 每个节点最多有 2 个子节点
- 根节点没有父节点
- 叶节点没有子节点
- 高度:从根节点到叶节点的最长路径
- 深度:从根节点到某节点的距离
**二叉树类型**
- **满二叉树**:每个节点有 0 或 2 个子节点
- **完全二叉树**:除最后一层外,所有层都被填满,且最后一层从左向右填充
- **完美二叉树**:所有内部节点都有 2 个子节点,所有叶节点在同一层
- **平衡二叉树**:左右子树的高度差 ≤ 1
### 节点结构
**Python**
```python
class TreeNode:
def __init__(self, val=0, left=None, right=None):
self.val = val
self.left = left
self.right = right
```
**JavaScript**
```javascript
class TreeNode {
constructor(val = 0, left = null, right = null) {
this.val = val;
this.left = left;
this.right = right;
}
}
```
---
## 树的遍历
### 1. 深度优先搜索(DFS
#### 中序遍历(左 → 根 → 右)
**用途**BST 可得到有序序列
```python
def inorder(root):
result = []
def traverse(node):
if not node:
return
traverse(node.left)
result.append(node.val)
traverse(node.right)
traverse(root)
return result
```
#### 前序遍历(根 → 左 → 右)
**用途**:复制树、前缀表达式
```python
def preorder(root):
result = []
def traverse(node):
if not node:
return
result.append(node.val)
traverse(node.left)
traverse(node.right)
traverse(root)
return result
```
#### 后序遍历(左 → 右 → 根)
**用途**:删除树、后缀表达式
```python
def postorder(root):
result = []
def traverse(node):
if not node:
return
traverse(node.left)
traverse(node.right)
result.append(node.val)
traverse(root)
return result
```
### 2. 广度优先搜索(BFS
**用途**:层序遍历、无权重树中的最短路径
```python
from collections import deque
def level_order(root):
if not root:
return []
result = []
queue = deque([root])
while queue:
level_size = len(queue)
current_level = []
for _ in range(level_size):
node = queue.popleft()
current_level.append(node.val)
if node.left:
queue.append(node.left)
if node.right:
queue.append(node.right)
result.append(current_level)
return result
```
**时间**O(n)**空间**O(w),其中 w 为最大宽度
---
## 二叉搜索树(BST
### 属性
- 左子树的值 < 节点值
- 右子树的值 > 节点值
- 左右子树也都是 BST
- 中序遍历得到有序序列
### 常见操作
#### 查找
```python
def search_bst(root, val):
if not root or root.val == val:
return root
if val < root.val:
return search_bst(root.left, val)
return search_bst(root.right, val)
```
**时间**:O(h),其中 h 为高度(平衡时 O(log n),最坏 O(n)
#### 插入
```python
def insert_bst(root, val):
if not root:
return TreeNode(val)
if val < root.val:
root.left = insert_bst(root.left, val)
else:
root.right = insert_bst(root.right, val)
return root
```
#### 删除
```python
def delete_bst(root, val):
if not root:
return None
if val < root.val:
root.left = delete_bst(root.left, val)
elif val > root.val:
root.right = delete_bst(root.right, val)
else:
# 找到待删除节点
# 情况 1:无子节点
if not root.left and not root.right:
return None
# 情况 2:只有一个子节点
if not root.left:
return root.right
if not root.right:
return root.left
# 情况 3:有两个子节点
# 寻找中序后继(右子树中的最小值)
min_node = find_min(root.right)
root.val = min_node.val
root.right = delete_bst(root.right, min_node.val)
return root
def find_min(node):
while node.left:
node = node.left
return node
```
---
## 常见树算法
### 1. 树的高度/深度
```python
def max_depth(root):
if not root:
return 0
return 1 + max(max_depth(root.left), max_depth(root.right))
```
### 2. 平衡树检查
```python
def is_balanced(root):
def height(node):
if not node:
return 0
left_height = height(node.left)
if left_height == -1:
return -1
right_height = height(node.right)
if right_height == -1:
return -1
if abs(left_height - right_height) > 1:
return -1
return 1 + max(left_height, right_height)
return height(root) != -1
```
### 3. 最近公共祖先(BST
```python
def lowest_common_ancestor_bst(root, p, q):
if p.val < root.val and q.val < root.val:
return lowest_common_ancestor_bst(root.left, p, q)
if p.val > root.val and q.val > root.val:
return lowest_common_ancestor_bst(root.right, p, q)
return root
```
### 4. 二叉树的直径
```python
def diameter_of_binary_tree(root):
diameter = 0
def height(node):
nonlocal diameter
if not node:
return 0
left = height(node.left)
right = height(node.right)
diameter = max(diameter, left + right)
return 1 + max(left, right)
height(root)
return diameter
```
### 5. 序列化与反序列化
```python
def serialize(root):
"""将树编码为字符串。"""
def helper(node):
if not node:
return 'null,'
return str(node.val) + ',' + helper(node.left) + helper(node.right)
return helper(root)
def deserialize(data):
"""将字符串解码为树。"""
def helper(nodes):
val = next(nodes)
if val == 'null':
return None
node = TreeNode(int(val))
node.left = helper(nodes)
node.right = helper(nodes)
return node
return helper(iter(data.split(',')))
```
---
## 图
### 核心概念
**图**是由边连接的节点(顶点)集合。
**类型**
- **有向图**与**无向图**:边是否有方向
- **有权图**与**无权图**:边是否带有权重
- **有环图**与**无环图**:是否包含环
- **连通图**与**非连通图**:所有节点之间是否存在路径
### 表示方法
#### 1. 邻接表(最常用)
```python
# 无向图
graph = {
'A': ['B', 'C'],
'B': ['A', 'D', 'E'],
'C': ['A', 'F'],
'D': ['B'],
'E': ['B', 'F'],
'F': ['C', 'E']
}
# 或使用 defaultdict
from collections import defaultdict
graph = defaultdict(list)
graph['A'].append('B')
graph['B'].append('A')
```
**空间**O(V + E)
#### 2. 邻接矩阵
```python
# graph[i][j] = 1 表示存在从 i 到 j 的边
n = 5 # 顶点数
graph = [[0] * n for _ in range(n)]
graph[0][1] = 1 # 从 0 到 1 的边
graph[1][0] = 1 # 从 1 到 0 的边(无向)
```
**空间**O(V²)
---
## 图的遍历
### 1. 深度优先搜索(DFS
**递归**
```python
def dfs(graph, start, visited=None):
if visited is None:
visited = set()
visited.add(start)
print(start)
for neighbor in graph[start]:
if neighbor not in visited:
dfs(graph, neighbor, visited)
return visited
```
**迭代**(使用栈):
```python
def dfs_iterative(graph, start):
visited = set()
stack = [start]
while stack:
node = stack.pop()
if node not in visited:
visited.add(node)
print(node)
for neighbor in graph[node]:
if neighbor not in visited:
stack.append(neighbor)
return visited
```
**时间**O(V + E)**空间**O(V)
### 2. 广度优先搜索(BFS
```python
from collections import deque
def bfs(graph, start):
visited = set([start])
queue = deque([start])
while queue:
node = queue.popleft()
print(node)
for neighbor in graph[node]:
if neighbor not in visited:
visited.add(neighbor)
queue.append(neighbor)
return visited
```
**时间**O(V + E)**空间**O(V)
---
## 常见图算法
### 1. 环检测(无向图)
```python
def has_cycle(graph):
visited = set()
def dfs(node, parent):
visited.add(node)
for neighbor in graph[node]:
if neighbor not in visited:
if dfs(neighbor, node):
return True
elif neighbor != parent:
return True # 发现环
return False
for node in graph:
if node not in visited:
if dfs(node, None):
return True
return False
```
### 2. 环检测(有向图)
```python
def has_cycle_directed(graph):
WHITE, GRAY, BLACK = 0, 1, 2
color = {node: WHITE for node in graph}
def dfs(node):
color[node] = GRAY
for neighbor in graph[node]:
if color[neighbor] == GRAY:
return True # 发现回边
if color[neighbor] == WHITE and dfs(neighbor):
return True
color[node] = BLACK
return False
for node in graph:
if color[node] == WHITE:
if dfs(node):
return True
return False
```
### 3. 拓扑排序(DAG
```python
def topological_sort(graph):
visited = set()
stack = []
def dfs(node):
visited.add(node)
for neighbor in graph[node]:
if neighbor not in visited:
dfs(neighbor)
stack.append(node)
for node in graph:
if node not in visited:
dfs(node)
return stack[::-1] # 反转
```
**时间**O(V + E)
### 4. 最短路径(无权图 - BFS)
```python
from collections import deque
def shortest_path_bfs(graph, start, end):
queue = deque([(start, [start])])
visited = set([start])
while queue:
node, path = queue.popleft()
if node == end:
return path
for neighbor in graph[node]:
if neighbor not in visited:
visited.add(neighbor)
queue.append((neighbor, path + [neighbor]))
return None # 未找到路径
```
### 5. Dijkstra 算法(有权图)
```python
import heapq
def dijkstra(graph, start):
"""找到从起点到所有节点的最短路径。"""
distances = {node: float('inf') for node in graph}
distances[start] = 0
pq = [(0, start)] # (距离, 节点)
while pq:
current_dist, current_node = heapq.heappop(pq)
if current_dist > distances[current_node]:
continue
for neighbor, weight in graph[current_node]:
distance = current_dist + weight
if distance < distances[neighbor]:
distances[neighbor] = distance
heapq.heappush(pq, (distance, neighbor))
return distances
```
**时间**O((V + E) log V)(使用最小堆)
### 6. 并查集(不相交集合)
```python
class UnionFind:
def __init__(self, n):
self.parent = list(range(n))
self.rank = [0] * n
def find(self, x):
if self.parent[x] != x:
self.parent[x] = self.find(self.parent[x]) # 路径压缩
return self.parent[x]
def union(self, x, y):
root_x = self.find(x)
root_y = self.find(y)
if root_x == root_y:
return False
# 按秩合并
if self.rank[root_x] < self.rank[root_y]:
self.parent[root_x] = root_y
elif self.rank[root_x] > self.rank[root_y]:
self.parent[root_y] = root_x
else:
self.parent[root_y] = root_x
self.rank[root_x] += 1
return True
```
**用途**:环检测、Kruskal 最小生成树、连通分量
---
## 常见图问题
### 1. 岛屿数量
```python
def num_islands(grid):
if not grid:
return 0
count = 0
rows, cols = len(grid), len(grid[0])
def dfs(r, c):
if (r < 0 or r >= rows or c < 0 or c >= cols or
grid[r][c] == '0'):
return
grid[r][c] = '0' # 标记为已访问
dfs(r + 1, c)
dfs(r - 1, c)
dfs(r, c + 1)
dfs(r, c - 1)
for r in range(rows):
for c in range(cols):
if grid[r][c] == '1':
count += 1
dfs(r, c)
return count
```
### 2. 课程表(环检测)
```python
def can_finish(num_courses, prerequisites):
graph = defaultdict(list)
for course, prereq in prerequisites:
graph[course].append(prereq)
WHITE, GRAY, BLACK = 0, 1, 2
color = [WHITE] * num_courses
def has_cycle(course):
color[course] = GRAY
for prereq in graph[course]:
if color[prereq] == GRAY:
return True
if color[prereq] == WHITE and has_cycle(prereq):
return True
color[course] = BLACK
return False
for course in range(num_courses):
if color[course] == WHITE:
if has_cycle(course):
return False
return True
```
### 3. 克隆图
```python
def clone_graph(node):
if not node:
return None
clones = {}
def dfs(node):
if node in clones:
return clones[node]
clone = Node(node.val)
clones[node] = clone
for neighbor in node.neighbors:
clone.neighbors.append(dfs(neighbor))
return clone
return dfs(node)
```
---
## 何时使用何种方法
**树的遍历**
- **DFS(中序)**BST → 有序序列
- **DFS(前序)**:复制树、前缀表示法
- **DFS(后序)**:删除树、后缀表示法
- **BFS**:层序遍历、最短路径
**图的遍历**
- **DFS**:环检测、拓扑排序、连通分量
- **BFS**:最短路径(无权图)、按层探索
**最短路径**
- **BFS**:无权图
- **Dijkstra**:有权图(非负权重)
- **Bellman-Ford**:有权图(可含负权重)
- **Floyd-Warshall**:所有点对最短路径
**树/图表示选择**
- **邻接表**:稀疏图(E << V²)
- **邻接矩阵**:稠密图、快速边查询
@@ -0,0 +1,580 @@
# 创建型设计模式
创建型模式处理对象的创建机制,试图以适合当前情境的方式创建对象。
---
## 1. 单例模式(Singleton Pattern
### 问题
你需要一个类的唯一实例(例如,数据库连接、配置管理器、日志记录器)。
### 反面示例
```python
# 可以创建多个实例
class DatabaseConnection:
def __init__(self):
self.connection = self.connect()
def connect(self):
print("Connecting to database...")
return "DB Connection"
# 问题:创建了多个连接
db1 = DatabaseConnection()
db2 = DatabaseConnection()
print(db1 is db2) # False — 不同的实例!
```
### 解决方案
```python
class Singleton:
_instance = None
def __new__(cls):
if cls._instance is None:
cls._instance = super().__new__(cls)
return cls._instance
class DatabaseConnection(Singleton):
def __init__(self):
if not hasattr(self, 'initialized'):
self.connection = self.connect()
self.initialized = True
def connect(self):
print("Connecting to database...")
return "DB Connection"
# 使用示例
db1 = DatabaseConnection()
db2 = DatabaseConnection()
print(db1 is db2) # True — 同一个实例!
```
### JavaScript 实现
```javascript
class DatabaseConnection {
constructor() {
if (DatabaseConnection.instance) {
return DatabaseConnection.instance;
}
this.connection = this.connect();
DatabaseConnection.instance = this;
}
connect() {
console.log("Connecting to database...");
return "DB Connection";
}
}
// 使用示例
const db1 = new DatabaseConnection();
const db2 = new DatabaseConnection();
console.log(db1 === db2); // true
```
### 何时使用
- **适用**:日志记录器、配置管理、连接池、缓存
- **不适用**:当你需要多个实例时,或用于简单工具类(改用模块)
### 优缺点
✅ 对唯一实例的受控访问
✅ 延迟初始化(Lazy initialization
❌ 全局状态(可能增加测试难度)
❌ 可能违反单一职责原则(Single Responsibility Principle
---
## 2. 工厂模式(Factory Pattern
### 问题
你需要在未指定具体类的情况下创建对象。创建逻辑复杂或依赖于条件。
### 反面示例
```python
# 客户端代码需要了解所有具体类
class Dog:
def speak(self):
return "Woof!"
class Cat:
def speak(self):
return "Meow!"
# 客户端必须知道实例化哪个类
def get_pet(pet_type):
if pet_type == "dog":
return Dog()
elif pet_type == "cat":
return Cat()
# 添加新宠物类型需要修改此函数!
```
### 解决方案
```python
from abc import ABC, abstractmethod
# 抽象产品
class Animal(ABC):
@abstractmethod
def speak(self):
pass
# 具体产品
class Dog(Animal):
def speak(self):
return "Woof!"
class Cat(Animal):
def speak(self):
return "Meow!"
class Bird(Animal):
def speak(self):
return "Tweet!"
# 工厂
class AnimalFactory:
@staticmethod
def create_animal(animal_type):
animals = {
'dog': Dog,
'cat': Cat,
'bird': Bird
}
animal_class = animals.get(animal_type.lower())
if animal_class:
return animal_class()
raise ValueError(f"Unknown animal type: {animal_type}")
# 使用示例
factory = AnimalFactory()
pet = factory.create_animal('dog')
print(pet.speak()) # Woof!
```
### JavaScript 实现
```javascript
class Animal {
speak() {
throw new Error("Method must be implemented");
}
}
class Dog extends Animal {
speak() {
return "Woof!";
}
}
class Cat extends Animal {
speak() {
return "Meow!";
}
}
class AnimalFactory {
static createAnimal(animalType) {
const animals = {
dog: Dog,
cat: Cat
};
const AnimalClass = animals[animalType.toLowerCase()];
if (AnimalClass) {
return new AnimalClass();
}
throw new Error(`Unknown animal type: ${animalType}`);
}
}
// 使用示例
const pet = AnimalFactory.createAnimal('dog');
console.log(pet.speak()); // Woof!
```
### 何时使用
- **适用**:当你事先不知道确切类型时,或创建逻辑较为复杂
- **不适用**:用于没有变化的简单对象创建
### 优缺点
✅ 客户端与产品之间的松耦合
✅ 易于添加新产品(开闭原则,Open/Closed Principle
✅ 集中化的创建逻辑
❌ 可能引入大量类
---
## 3. 抽象工厂模式(Abstract Factory Pattern
### 问题
你需要在未指定具体类的情况下创建一组相关的对象家族。
### 示例:UI 主题工厂
```python
from abc import ABC, abstractmethod
# 抽象产品
class Button(ABC):
@abstractmethod
def render(self):
pass
class Checkbox(ABC):
@abstractmethod
def render(self):
pass
# 具体产品 —— 浅色主题
class LightButton(Button):
def render(self):
return "Rendering light button"
class LightCheckbox(Checkbox):
def render(self):
return "Rendering light checkbox"
# 具体产品 —— 深色主题
class DarkButton(Button):
def render(self):
return "Rendering dark button"
class DarkCheckbox(Checkbox):
def render(self):
return "Rendering dark checkbox"
# 抽象工厂
class UIFactory(ABC):
@abstractmethod
def create_button(self):
pass
@abstractmethod
def create_checkbox(self):
pass
# 具体工厂
class LightThemeFactory(UIFactory):
def create_button(self):
return LightButton()
def create_checkbox(self):
return LightCheckbox()
class DarkThemeFactory(UIFactory):
def create_button(self):
return DarkButton()
def create_checkbox(self):
return DarkCheckbox()
# 客户端代码
def create_ui(factory: UIFactory):
button = factory.create_button()
checkbox = factory.create_checkbox()
return button.render(), checkbox.render()
# 使用示例
light_factory = LightThemeFactory()
print(create_ui(light_factory))
dark_factory = DarkThemeFactory()
print(create_ui(dark_factory))
```
### 何时使用
- **适用**:当你需要一组相关的对象协同工作时
- **不适用**:当你只有一个产品家族时
---
## 4. 构建器模式(Builder Pattern
### 问题
你需要逐步构建复杂对象。构造函数参数过多。
### 反面示例
```python
# 构造函数参数过多
class Pizza:
def __init__(self, size, cheese=False, pepperoni=False,
mushrooms=False, onions=False, bacon=False,
ham=False, pineapple=False):
self.size = size
self.cheese = cheese
self.pepperoni = pepperoni
# ... 大量参数
# 难以阅读,容易出错
pizza = Pizza(12, True, True, False, True, False, True, False)
```
### 解决方案
```python
class Pizza:
def __init__(self, size):
self.size = size
self.cheese = False
self.pepperoni = False
self.mushrooms = False
self.onions = False
self.bacon = False
def __str__(self):
toppings = []
if self.cheese:
toppings.append("cheese")
if self.pepperoni:
toppings.append("pepperoni")
if self.mushrooms:
toppings.append("mushrooms")
if self.onions:
toppings.append("onions")
if self.bacon:
toppings.append("bacon")
return f"{self.size}\" pizza with {', '.join(toppings)}"
class PizzaBuilder:
def __init__(self, size):
self.pizza = Pizza(size)
def add_cheese(self):
self.pizza.cheese = True
return self
def add_pepperoni(self):
self.pizza.pepperoni = True
return self
def add_mushrooms(self):
self.pizza.mushrooms = True
return self
def add_onions(self):
self.pizza.onions = True
return self
def add_bacon(self):
self.pizza.bacon = True
return self
def build(self):
return self.pizza
# 使用示例 —— 可读性大大提升!
pizza = (PizzaBuilder(12)
.add_cheese()
.add_pepperoni()
.add_mushrooms()
.build())
print(pizza) # 12" pizza with cheese, pepperoni, mushrooms
```
### JavaScript 实现
```javascript
class Pizza {
constructor(size) {
this.size = size;
this.toppings = [];
}
toString() {
return `${this.size}" pizza with ${this.toppings.join(', ')}`;
}
}
class PizzaBuilder {
constructor(size) {
this.pizza = new Pizza(size);
}
addCheese() {
this.pizza.toppings.push('cheese');
return this;
}
addPepperoni() {
this.pizza.toppings.push('pepperoni');
return this;
}
addMushrooms() {
this.pizza.toppings.push('mushrooms');
return this;
}
build() {
return this.pizza;
}
}
// 使用示例
const pizza = new PizzaBuilder(12)
.addCheese()
.addPepperoni()
.addMushrooms()
.build();
console.log(pizza.toString());
```
### 何时使用
- **适用**:构造函数参数多、需要逐步构建、需要不可变对象
- **不适用**:参数少的简单对象
### 优缺点
✅ 可读性强的流畅接口(Fluent Interface
✅ 对构建过程的精细控制
✅ 可以创建不同的表示形式
❌ 代码量增加(需要构建器类)
---
## 5. 原型模式(Prototype Pattern
### 问题
你需要复制现有对象,而不让代码依赖于它们的类。
### 解决方案
```python
import copy
class Prototype:
def clone(self):
"""对象的深拷贝。"""
return copy.deepcopy(self)
class Shape(Prototype):
def __init__(self, shape_type, color):
self.shape_type = shape_type
self.color = color
self.coordinates = []
def __str__(self):
return f"{self.color} {self.shape_type} at {self.coordinates}"
# 使用示例
original = Shape("Circle", "Red")
original.coordinates = [10, 20]
# 克隆
clone = original.clone()
clone.color = "Blue"
clone.coordinates = [30, 40]
print(original) # Red Circle at [10, 20]
print(clone) # Blue Circle at [30, 40]
```
### JavaScript 实现
```javascript
class Shape {
constructor(shapeType, color) {
this.shapeType = shapeType;
this.color = color;
this.coordinates = [];
}
clone() {
const cloned = Object.create(Object.getPrototypeOf(this));
cloned.shapeType = this.shapeType;
cloned.color = this.color;
cloned.coordinates = [...this.coordinates];
return cloned;
}
toString() {
return `${this.color} ${this.shapeType} at ${this.coordinates}`;
}
}
// 使用示例
const original = new Shape("Circle", "Red");
original.coordinates = [10, 20];
const clone = original.clone();
clone.color = "Blue";
clone.coordinates = [30, 40];
console.log(original.toString()); // Red Circle at 10,20
console.log(clone.toString()); // Blue Circle at 30,40
```
### 何时使用
- **适用**:对象创建成本高,需要大量相似对象
- **不适用**:简单对象,浅拷贝即可满足需求
---
## 模式选择指南
| 模式 | 适用场景 | 典型用例 |
|---------|----------|-------------------|
| **单例模式(Singleton** | 需要唯一实例 | 日志记录器、配置管理、数据库连接池 |
| **工厂模式(Factory** | 编译时不知道具体类 | 插件系统、文档类型 |
| **抽象工厂模式(Abstract Factory** | 需要一组相关的对象 | UI 主题、跨平台应用 |
| **构建器模式(Builder** | 参数众多的复杂构建过程 | 查询构建器、文档构建器 |
| **原型模式(Prototype** | 创建成本高,需要副本 | 游戏实体、图形编辑器 |
---
## 应避免的反模式
### 1. 过度使用单例
```python
# 不要把所有东西都做成单例
class MathUtils(Singleton): # 糟糕 —— 直接使用模块即可!
@staticmethod
def add(a, b):
return a + b
# 应使用模块级函数
def add(a, b):
return a + b
```
### 2. 上帝工厂
```python
# 不要用一个工厂处理所有事情
class GodFactory:
def create_user(self): ...
def create_product(self): ...
def create_order(self): ...
# ... 还有 50 多个方法
# 应按不同关注点使用独立的工厂
class UserFactory: ...
class ProductFactory: ...
class OrderFactory: ...
```
### 3. 过早抽象
```python
# 不要在简单情况下创建工厂
class DogFactory:
@staticmethod
def create():
return Dog() # 只有一个简单的类
# 应直接实例化
dog = Dog()
```
---
## 关键要点
1. **单例模式**:唯一实例,全局访问
2. **工厂模式**:将对象创建与使用解耦
3. **抽象工厂模式**:一组相关的对象家族
4. **构建器模式**:逐步构建复杂对象
5. **原型模式**:克隆现有对象
**请记住**:在模式确实能解决实际问题时再使用。不要在模式不适用时强行套用!
@@ -0,0 +1,8 @@
# 平台常用高分 Skill Top 200v2
来源:`manifest.top200-v2.json` — Phase 3 当前可比组评测胜出 + 网页版 agent 选品策略(见 `reports/phase3/top200-v2-selection-policy.md`)。
- 复制 skill 数:200
- 清单:`manifest.top200-v2.json` / `manifest.top200-v2.csv`
- skill 目录:`skills/``{rank:03d}__{original_skill_id}`
- 同步命令:`python3 reports/phase3/scripts/sync_top200_skills.py`
+656
View File
@@ -0,0 +1,656 @@
# Python 快速参考
## 基本语法
### 变量与类型
```python
# 动态类型
x = 5 # int
y = 3.14 # float
name = "Alice" # str
is_valid = True # bool
# 类型提示(可选,Python 3.5+
def greet(name: str) -> str:
return f"Hello, {name}"
# 多重赋值
a, b, c = 1, 2, 3
x = y = z = 0
```
### 字符串
```python
# 字符串创建
s = "hello"
s = 'hello'
s = """multi
line"""
# F-字符串(Python 3.6+
name = "Alice"
age = 30
message = f"{name} is {age} years old"
# 常用方法
s.upper() # "HELLO"
s.lower() # "hello"
s.strip() # 移除空白字符
s.split(',') # 拆分为列表
s.replace('h', 'H') # "Hello"
s.startswith('he') # True
s.endswith('lo') # True
s.find('ll') # 2(索引,未找到返回 -1
# 切片
s[0] # 'h'
s[-1] # 'o'
s[1:4] # 'ell'
s[::-1] # 'olleh'(反转)
```
### 列表
```python
# 创建
nums = [1, 2, 3, 4, 5]
mixed = [1, "hello", True, 3.14]
# 常用操作
nums.append(6) # 添加到末尾
nums.insert(0, 0) # 在指定索引处插入
nums.remove(3) # 移除首次出现的元素
nums.pop() # 移除并返回最后一个元素
nums.pop(0) # 移除并返回指定索引的元素
nums.extend([7, 8]) # 添加多个元素
len(nums) # 长度
nums.sort() # 原地排序
sorted(nums) # 返回排序后的副本
nums.reverse() # 原地反转
nums[::-1] # 返回反转后的副本
# 列表推导式
squares = [x**2 for x in range(10)]
evens = [x for x in range(10) if x % 2 == 0]
```
### 字典
```python
# 创建
person = {'name': 'Alice', 'age': 30}
person = dict(name='Alice', age=30)
# 访问
name = person['name'] # 键不存在时抛出 KeyError
name = person.get('name') # 键不存在时返回 None
name = person.get('name', 'Unknown') # 指定默认值
# 修改
person['city'] = 'NYC' # 添加/更新
del person['age'] # 删除
age = person.pop('age', 0) # 删除并返回
# 迭代
for key in person:
print(key, person[key])
for key, value in person.items():
print(key, value)
# 字典推导式
squares = {x: x**2 for x in range(5)}
```
### 集合
```python
# 创建
s = {1, 2, 3, 4, 5}
s = set([1, 2, 3, 3, 3]) # {1, 2, 3}
# 操作
s.add(6) # 添加元素
s.remove(3) # 移除(元素不存在时抛出 KeyError)
s.discard(3) # 移除(元素不存在时不报错)
s.union({4, 5, 6}) # {1, 2, 3, 4, 5, 6}
s.intersection({3, 4}) # {3, 4}
s.difference({3, 4}) # {1, 2, 5}
```
---
## 控制流
### If-Elif-Else
```python
x = 10
if x > 0:
print("Positive")
elif x < 0:
print("Negative")
else:
print("Zero")
# 三元表达式
result = "Positive" if x > 0 else "Non-positive"
```
### 循环
```python
# For 循环
for i in range(5): # 0, 1, 2, 3, 4
print(i)
for i in range(2, 10, 2): # 2, 4, 6, 8
print(i)
for item in [1, 2, 3]:
print(item)
# Enumerate(索引 + 值)
for i, val in enumerate(['a', 'b', 'c']):
print(f"{i}: {val}")
# While 循环
i = 0
while i < 5:
print(i)
i += 1
# Break 和 continue
for i in range(10):
if i == 3:
continue # 跳过 3
if i == 8:
break # 在 8 处停止
print(i)
```
---
## 函数
### 基本函数
```python
def greet(name):
return f"Hello, {name}"
# 默认参数
def greet(name="World"):
return f"Hello, {name}"
# 多个返回值
def divide(a, b):
return a // b, a % b # 返回元组
quotient, remainder = divide(10, 3)
# *args 和 **kwargs
def print_all(*args):
for arg in args:
print(arg)
def print_info(**kwargs):
for key, value in kwargs.items():
print(f"{key}: {value}")
print_all(1, 2, 3)
print_info(name="Alice", age=30)
```
### Lambda 函数
```python
# 匿名函数
square = lambda x: x ** 2
add = lambda x, y: x + y
# 常用于 map、filter、sorted
nums = [1, 2, 3, 4, 5]
squares = list(map(lambda x: x**2, nums))
evens = list(filter(lambda x: x % 2 == 0, nums))
sorted_tuples = sorted([(1, 'c'), (2, 'a')], key=lambda x: x[1])
```
---
## 面向对象编程
### 类
```python
class Person:
# 类变量
species = "Homo sapiens"
def __init__(self, name, age):
# 实例变量
self.name = name
self.age = age
def greet(self):
return f"Hello, I'm {self.name}"
def __str__(self):
return f"Person(name={self.name}, age={self.age})"
def __repr__(self):
return f"Person('{self.name}', {self.age})"
# 使用
p = Person("Alice", 30)
print(p.greet())
print(p) # 使用 __str__
```
### 继承
```python
class Animal:
def __init__(self, name):
self.name = name
def speak(self):
pass
class Dog(Animal):
def speak(self):
return f"{self.name} says Woof!"
class Cat(Animal):
def speak(self):
return f"{self.name} says Meow!"
dog = Dog("Buddy")
print(dog.speak()) # Buddy says Woof!
```
### 属性
```python
class Circle:
def __init__(self, radius):
self._radius = radius
@property
def radius(self):
return self._radius
@radius.setter
def radius(self, value):
if value < 0:
raise ValueError("Radius cannot be negative")
self._radius = value
@property
def area(self):
return 3.14159 * self._radius ** 2
# 使用
c = Circle(5)
print(c.area) # 78.53975
c.radius = 10 # 使用 setter
```
### 特殊方法(魔术方法)
```python
class Vector:
def __init__(self, x, y):
self.x = x
self.y = y
def __add__(self, other):
return Vector(self.x + other.x, self.y + other.y)
def __str__(self):
return f"Vector({self.x}, {self.y})"
def __len__(self):
return 2
def __getitem__(self, index):
return [self.x, self.y][index]
v1 = Vector(1, 2)
v2 = Vector(3, 4)
v3 = v1 + v2 # 使用 __add__
print(v3) # 使用 __str__
```
---
## 文件 I/O
```python
# 读取
with open('file.txt', 'r') as f:
content = f.read() # 读取整个文件
# 或
lines = f.readlines() # 读取为行列表
# 或
for line in f: # 逐行迭代
print(line.strip())
# 写入
with open('file.txt', 'w') as f:
f.write("Hello\n")
f.writelines(["Line 1\n", "Line 2\n"])
# 追加
with open('file.txt', 'a') as f:
f.write("New line\n")
# JSON
import json
# 写入 JSON
data = {'name': 'Alice', 'age': 30}
with open('data.json', 'w') as f:
json.dump(data, f, indent=2)
# 读取 JSON
with open('data.json', 'r') as f:
data = json.load(f)
```
---
## 错误处理
```python
# Try-except
try:
result = 10 / 0
except ZeroDivisionError:
print("Cannot divide by zero")
except Exception as e:
print(f"Error: {e}")
else:
print("No errors") # 未发生异常时执行
finally:
print("Always runs") # 始终执行
# 抛出异常
def divide(a, b):
if b == 0:
raise ValueError("Divisor cannot be zero")
return a / b
# 自定义异常
class InvalidAgeError(Exception):
pass
def set_age(age):
if age < 0:
raise InvalidAgeError("Age cannot be negative")
```
---
## 常用库
### Collections
```python
from collections import Counter, defaultdict, deque
# Counter
words = ['apple', 'banana', 'apple', 'orange', 'banana', 'apple']
count = Counter(words)
print(count['apple']) # 3
print(count.most_common(2)) # [('apple', 3), ('banana', 2)]
# defaultdict
d = defaultdict(list)
d['key'].append(1) # 不会抛出 KeyError
# deque(双端队列)
q = deque([1, 2, 3])
q.append(4) # 从右侧添加
q.appendleft(0) # 从左侧添加
q.pop() # 从右侧移除
q.popleft() # 从左侧移除
```
### Itertools
```python
from itertools import combinations, permutations, product
# 组合
list(combinations([1, 2, 3], 2)) # [(1, 2), (1, 3), (2, 3)]
# 排列
list(permutations([1, 2, 3], 2)) # [(1, 2), (1, 3), (2, 1), ...]
# 笛卡尔积
list(product([1, 2], ['a', 'b'])) # [(1, 'a'), (1, 'b'), (2, 'a'), (2, 'b')]
```
### Functools
```python
from functools import lru_cache, reduce
# 记忆化
@lru_cache(maxsize=None)
def fibonacci(n):
if n < 2:
return n
return fibonacci(n-1) + fibonacci(n-2)
# Reduce
from functools import reduce
product = reduce(lambda x, y: x * y, [1, 2, 3, 4]) # 24
```
---
## 列表/字典/集合推导式
```python
# 列表推导式
squares = [x**2 for x in range(10)]
evens = [x for x in range(10) if x % 2 == 0]
nested = [[i for i in range(3)] for j in range(3)]
# 字典推导式
squares_dict = {x: x**2 for x in range(5)}
filtered = {k: v for k, v in squares_dict.items() if v > 5}
# 集合推导式
unique_lengths = {len(word) for word in ['apple', 'banana', 'kiwi']}
# 生成器表达式(内存高效)
sum_of_squares = sum(x**2 for x in range(1000000))
```
---
## 有用的内置函数
```python
# any, all
any([False, True, False]) # True(至少一个为 True
all([True, True, True]) # True(全部为 True
# zip
names = ['Alice', 'Bob']
ages = [30, 25]
for name, age in zip(names, ages):
print(f"{name}: {age}")
# enumerate
for i, val in enumerate(['a', 'b', 'c']):
print(f"{i}: {val}")
# map, filter
nums = [1, 2, 3, 4, 5]
squared = list(map(lambda x: x**2, nums))
evens = list(filter(lambda x: x % 2 == 0, nums))
# sorted, reversed
sorted([3, 1, 2]) # [1, 2, 3]
sorted([3, 1, 2], reverse=True) # [3, 2, 1]
list(reversed([1, 2, 3])) # [3, 2, 1]
# max, min, sum
max([1, 5, 3]) # 5
min([1, 5, 3]) # 1
sum([1, 2, 3]) # 6
```
---
## 常用惯用法
### 变量交换
```python
a, b = b, a
```
### 三元运算符
```python
result = "Even" if x % 2 == 0 else "Odd"
```
### 字典默认值
```python
value = my_dict.get('key', default_value)
```
### 带起始值的 Enumerate
```python
for i, val in enumerate(items, start=1):
print(f"{i}. {val}")
```
### 解包
```python
first, *middle, last = [1, 2, 3, 4, 5]
# first=1, middle=[2,3,4], last=5
```
### 上下文管理器
```python
with open('file.txt') as f:
data = f.read()
# 文件自动关闭
```
---
## 最佳实践
### 1. PEP 8 风格指南
```python
# 使用 4 个空格缩进
# 变量和函数使用 snake_case
# 类使用 PascalCase
# 常量使用大写
def calculate_total(items):
DISCOUNT_RATE = 0.1
total = sum(items)
return total * (1 - DISCOUNT_RATE)
```
### 2. 列表推导式 vs 循环
```python
# 简单转换优先使用推导式
squares = [x**2 for x in range(10)]
# 复杂逻辑使用循环
results = []
for x in range(10):
if x % 2 == 0:
result = process_even(x)
else:
result = process_odd(x)
results.append(result)
```
### 3. None 用 `is`,值比较用 `==`
```python
if value is None: # 正确
if value == None: # 也能工作但不推荐
```
### 4. EAFP 与 LBYL
```python
# 请求原谅比获得许可更容易(Pythonic 风格)
try:
value = my_dict['key']
except KeyError:
value = default
# 三思而后行(不够 Pythonic)
if 'key' in my_dict:
value = my_dict['key']
else:
value = default
```
---
## 常见陷阱
### 1. 可变默认参数
```python
# 错误
def append_to(element, lst=[]):
lst.append(element)
return lst
# 所有调用共享同一个列表!
print(append_to(1)) # [1]
print(append_to(2)) # [1, 2] — 不符合预期!
# 正确
def append_to(element, lst=None):
if lst is None:
lst = []
lst.append(element)
return lst
```
### 2. 闭包延迟绑定
```python
# 错误
funcs = [lambda: i for i in range(5)]
print([f() for f in funcs]) # [4, 4, 4, 4, 4]
# 正确
funcs = [lambda i=i: i for i in range(5)]
print([f() for f in funcs]) # [0, 1, 2, 3, 4]
```
### 3. 遍历列表时修改
```python
# 错误
lst = [1, 2, 3, 4, 5]
for item in lst:
if item % 2 == 0:
lst.remove(item) # 可能跳过元素
# 正确
lst = [item for item in lst if item % 2 != 0]
```
---
## Python 3.10+ 特性
### 结构化模式匹配
```python
def process_command(command):
match command.split():
case ["quit"]:
return "Quitting"
case ["load", filename]:
return f"Loading {filename}"
case ["save", filename]:
return f"Saving {filename}"
case _:
return "Unknown command"
```
### 联合类型
```python
def greet(name: str | None = None) -> str:
if name is None:
return "Hello, stranger"
return f"Hello, {name}"
```
+26
View File
@@ -0,0 +1,26 @@
# 学习日志
本文档用于记录你在 Code Mentor 中的学习进度与成长历程。每次学习结束后,你的进度会自动保存。
## 学习历史
*随着你的学习,以下将记录每次的学习记录……*
---
## 已掌握知识点
*你已熟练掌握的主题将显示在这里……*
## 待复习内容
*需要进一步练习的主题将在此处追踪……*
## 学习目标
*你的学习目标将在此处追踪……*
---
**最近更新**:初始设置
**总学习次数**0