
1. 董付国老师Python小屋编程题解析系列作为一名长期关注Python教学领域的开发者我对董付国老师的编程题库一直保持着高度关注。这个系列题目以其实用性和渐进式的难度设计在Python学习者中享有很高的声誉。151-160这组题目延续了董老师一贯的出题风格既考察基础语法掌握程度又暗藏需要深入思考的编程技巧。这组题目特别适合已经掌握Python基础语法想要进一步提升编程能力的学习者。通过这10道题目的系统练习你能够巩固字符串、列表、字典等核心数据结构的操作掌握常见的算法实现思路理解Python特有的编程范式培养解决实际问题的思维模式2. 题目151字符串加密与解密2.1 题目要求分析这道题要求实现一个简单的字符串加密解密系统。具体要求是加密时将每个字符的ASCII码值加上其在字符串中的位置从0开始作为偏移量解密时执行相反操作需要考虑大小写字母和数字字符的处理def encrypt(text): result [] for index, char in enumerate(text): if char.isalpha() or char.isdigit(): offset index new_char chr(ord(char) offset) result.append(new_char) else: result.append(char) return .join(result) def decrypt(text): result [] for index, char in enumerate(text): if char.isalpha() or char.isdigit(): offset index new_char chr(ord(char) - offset) result.append(new_char) else: result.append(char) return .join(result)2.2 实现细节与注意事项在实际编码过程中有几个关键点需要注意边界处理当字符加上偏移量超出可打印ASCII范围时需要进行模运算处理性能优化对于长字符串使用列表推导式比字符串拼接效率更高异常处理需要考虑输入非字符串类型时的容错机制提示在实际应用中这种简单的加密算法安全性较低仅适合学习用途。生产环境中应使用标准加密库如hashlib或cryptography。3. 题目152矩阵对角线元素求和3.1 问题描述与解法给定一个N×N的方阵计算其两条对角线元素之和。如果矩阵维度为奇数中心元素不重复计算。def diagonal_sum(matrix): n len(matrix) total 0 for i in range(n): total matrix[i][i] # 主对角线 total matrix[i][n-1-i] # 副对角线 if n % 2 1: total - matrix[n//2][n//2] # 扣除重复计算的中间元素 return total3.2 进阶思考这个问题可以有多种变体非方阵处理如何修改算法使其适用于M×N的矩形矩阵并行计算对于超大矩阵如何利用多线程加速计算稀疏矩阵当矩阵大部分元素为0时如何优化存储和计算4. 题目153单词频率统计4.1 基础实现统计一段文本中各个单词出现的频率忽略大小写差异排除标点符号。import re from collections import defaultdict def word_frequency(text): words re.findall(r\b\w\b, text.lower()) frequency defaultdict(int) for word in words: frequency[word] 1 return dict(frequency)4.2 性能对比与优化对比几种不同实现方式的性能差异普通字典需要先检查key是否存在defaultdict代码更简洁Counter专为计数设计的工具from collections import Counter def word_frequency_counter(text): words re.findall(r\b\w\b, text.lower()) return dict(Counter(words))注意在处理超长文本时可以考虑分批读取和统计避免内存溢出。5. 题目154链表逆序5.1 单链表节点定义首先定义链表节点类class ListNode: def __init__(self, val0, nextNone): self.val val self.next next5.2 迭代法实现最直观的逆序方法是使用迭代def reverse_list(head): prev None current head while current: next_node current.next current.next prev prev current current next_node return prev5.3 递归法实现递归解法更简洁但可能引发栈溢出def reverse_list_recursive(head): if not head or not head.next: return head new_head reverse_list_recursive(head.next) head.next.next head head.next None return new_head6. 题目155最大公约数与最小公倍数6.1 辗转相除法实现计算两个数的最大公约数(GCD)def gcd(a, b): while b: a, b b, a % b return a6.2 最小公倍数计算利用GCD计算最小公倍数(LCM)def lcm(a, b): return a * b // gcd(a, b)6.3 性能分析与优化对于大整数二进制GCD算法(Stein算法)效率更高def binary_gcd(a, b): if a 0: return b if b 0: return a shift 0 while ((a | b) 1) 0: a 1 b 1 shift 1 while (a 1) 0: a 1 while b ! 0: while (b 1) 0: b 1 if a b: a, b b, a b - a return a shift7. 题目156日期差计算7.1 使用datetime模块Python标准库提供了完善的日期处理功能from datetime import datetime def days_between(date1, date2): date_format %Y-%m-%d d1 datetime.strptime(date1, date_format) d2 datetime.strptime(date2, date_format) delta abs((d2 - d1).days) return delta7.2 手动实现日期计算如果不使用标准库需要考虑闰年等复杂情况def is_leap(year): return year % 4 0 and (year % 100 ! 0 or year % 400 0) def days_in_month(year, month): if month in {4, 6, 9, 11}: return 30 if month 2: return 29 if is_leap(year) else 28 return 31 def date_to_days(year, month, day): total 0 for y in range(1, year): total 366 if is_leap(y) else 365 for m in range(1, month): total days_in_month(year, m) total day return total def manual_days_between(date1, date2): y1, m1, d1 map(int, date1.split(-)) y2, m2, d2 map(int, date2.split(-)) return abs(date_to_days(y2, m2, d2) - date_to_days(y1, m1, d1))8. 题目157二叉树层次遍历8.1 二叉树节点定义首先定义二叉树节点class TreeNode: def __init__(self, val0, leftNone, rightNone): self.val val self.left left self.right right8.2 队列实现层次遍历使用队列进行广度优先搜索from collections import deque def level_order(root): if not root: return [] queue deque([root]) result [] 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 result8.3 递归实现虽然不直观但也可以递归实现def level_order_recursive(root): levels [] if not root: return levels def helper(node, level): if len(levels) level: levels.append([]) levels[level].append(node.val) if node.left: helper(node.left, level 1) if node.right: helper(node.right, level 1) helper(root, 0) return levels9. 题目158素数生成器9.1 基础素数判断判断一个数是否为素数def is_prime(n): if n 1: return False if n 2: return True if n % 2 0: return False for i in range(3, int(n**0.5) 1, 2): if n % i 0: return False return True9.2 埃拉托斯特尼筛法高效生成素数列表的算法def sieve_of_eratosthenes(limit): sieve [True] * (limit 1) sieve[0] sieve[1] False for num in range(2, int(limit**0.5) 1): if sieve[num]: sieve[num*num : limit1 : num] [False]*len(sieve[num*num : limit1 : num]) primes [i for i, is_prime in enumerate(sieve) if is_prime] return primes9.3 生成器实现使用生成器实现惰性求值def prime_generator(): yield 2 primes [2] candidate 3 while True: is_prime True sqrt_candidate candidate ** 0.5 for p in primes: if p sqrt_candidate: break if candidate % p 0: is_prime False break if is_prime: primes.append(candidate) yield candidate candidate 210. 题目159装饰器实现函数计时10.1 基础计时装饰器测量函数执行时间的简单装饰器import time def timing_decorator(func): def wrapper(*args, **kwargs): start_time time.perf_counter() result func(*args, **kwargs) end_time time.perf_counter() print(f{func.__name__} executed in {end_time - start_time:.6f} seconds) return result return wrapper10.2 带参数的装饰器实现可以多次运行取平均值的计时装饰器def average_timing(runs10): def decorator(func): def wrapper(*args, **kwargs): total_time 0 for _ in range(runs): start_time time.perf_counter() result func(*args, **kwargs) total_time time.perf_counter() - start_time avg_time total_time / runs print(f{func.__name__} average execution over {runs} runs: {avg_time:.6f} seconds) return result return wrapper return decorator10.3 装饰器的高级应用装饰器可以用于各种场景日志记录权限验证缓存结果重试机制11. 题目160多线程下载管理器11.1 基础下载函数使用requests库实现单线程下载import requests def download_file(url, filename): response requests.get(url, streamTrue) with open(filename, wb) as f: for chunk in response.iter_content(chunk_size8192): if chunk: f.write(chunk)11.2 多线程下载实现使用concurrent.futures实现并行下载from concurrent.futures import ThreadPoolExecutor def download_multiple(urls, filenames, max_workers4): with ThreadPoolExecutor(max_workersmax_workers) as executor: futures [] for url, filename in zip(urls, filenames): futures.append(executor.submit(download_file, url, filename)) for future in futures: future.result() # 等待所有下载完成11.3 断点续传实现更健壮的下载器应该支持断点续传def resume_download(url, filename): headers {} if os.path.exists(filename): downloaded os.path.getsize(filename) headers[Range] fbytes{downloaded}- response requests.get(url, headersheaders, streamTrue) mode ab if headers else wb with open(filename, mode) as f: for chunk in response.iter_content(chunk_size8192): if chunk: f.write(chunk)在实际开发中151-160这组题目涵盖了Python编程的多个重要方面。通过系统练习这些题目我深刻体会到编程能力的提升不仅在于记住语法更在于培养解决问题的思维方式。每个题目都有多种解法尝试不同方法并比较它们的优劣是成为优秀程序员的关键。