跳转至

01 - 编程思维训练

目标:重建独立思考和编码能力

时间:1-2周

核心原则:先思考,再编码;先手写,再验证


🧠 什么是编程思维?

编程思维不是"记住语法",而是: 1. 问题分解:把大问题拆成小问题 2. 模式识别:发现问题的共性 3. 抽象思维:提取关键逻辑,忽略细节 4. 算法思维:设计解决问题的步骤

示例:从生活到代码

生活问题:整理书架

Text Only
步骤:
1. 把所有书拿出来
2. 按类别分类(小说、技术、历史...)
3. 每类按作者排序
4. 放回书架

编程问题:排序数组

Python
def sort_books(books):
    # 1. 分类
    categories = {}
    for book in books:
        cat = book.category
        if cat not in categories:
            categories[cat] = []
        categories[cat].append(book)

    # 2. 每类排序
    for cat in categories:
        categories[cat].sort(key=lambda b: b.author)  # lambda匿名函数:简洁的单行函数

    # 3. 合并
    result = []
    for cat in sorted(categories.keys()):
        result.extend(categories[cat])

    return result

核心:解决问题的思路是相通的!


🎯 训练方法

方法1:伪代码先行

规则:写代码之前,先用中文/英文写出解决步骤

练习1:找最大值

问题:给定一个数组,找出最大值

步骤1:写伪代码

Text Only
假设第一个数是最大值
遍历数组中的每个数:
    如果当前数比最大值还大:
        更新最大值
返回最大值

步骤2:翻译成代码

Python
def find_max(arr):
    if not arr:
        return None

    max_val = arr[0]  # 假设第一个数是最大值

    for num in arr:   # 遍历数组
        if num > max_val:  # 如果当前数更大
            max_val = num   # 更新最大值

    return max_val

练习2:判断回文

问题:判断一个字符串是否是回文(正读反读相同)

步骤1:写伪代码

Text Only
设置两个指针,一个在开头,一个在结尾
当左指针 < 右指针:
    如果左右字符不相同:
        不是回文,返回False
    左指针右移
    右指针左移
是回文,返回True

步骤2:翻译成代码

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:画图辅助思考

规则:复杂问题,先画图理清逻辑

练习3:反转链表

问题:反转一个单链表

步骤1:画图

Text Only
原始链表:
1 -> 2 -> 3 -> 4 -> None

反转后:
None <- 1 <- 2 <- 3 <- 4

过程:
prev   curr   next
None    1  ->  2  ->  3  ->  4

Step1: curr.next = prev
None <- 1     2  ->  3  ->  4

Step2: 移动指针
       prev   curr   next
        1  ->  2  ->  3  ->  4

步骤2:写代码

Python
def reverse_list(head):
    prev = None
    curr = head

    while curr:
        next_temp = curr.next  # 保存下一个节点
        curr.next = prev       # 反转指针
        prev = curr           # prev前移
        curr = next_temp      # curr前移

    return prev

方法3:边界条件思维

规则:写代码时,先考虑边界情况

常见边界条件

Python
# 1. 空输入
def process(arr):
    if not arr:  # 空数组
        return []
    # ...

# 2. 单个元素
def process(arr):
    if len(arr) == 1:
        return arr[0]
    # ...

# 3. 极端值
def divide(a, b):
    if b == 0:  # 除零
        raise ValueError("Cannot divide by zero")
    # ...

# 4. 类型检查
def process(data):
    if not isinstance(data, list):  # isinstance检查对象类型
        raise TypeError("Expected list")
    # ...

练习4:安全的数组访问

Python
def safe_get(arr, index):
    """安全地获取数组元素"""
    # 边界检查
    if not arr:  # 空数组
        return None

    if index < 0 or index >= len(arr):  # 索引越界
        return None

    return arr[index]

# 测试
print(safe_get([1, 2, 3], 1))    # 2
print(safe_get([1, 2, 3], 5))    # None
print(safe_get([], 0))           # None
print(safe_get([1, 2, 3], -1))   # None

📝 刻意练习

练习1:基础逻辑(1-3天)

要求:每个题目先写伪代码,再写代码

题目1:两数之和

给定一个数组和一个目标值,找出数组中和为目标值的两个数的索引。

Python
def two_sum(nums, target):
    """
    伪代码:
    1. 创建一个字典存储已遍历的数
    2. 遍历数组:
        计算 complement = target - 当前数
        如果 complement 在字典中:
            返回 [complement的索引, 当前索引]
        将当前数加入字典
    3. 如果没找到,返回空列表
    """
    # 你的代码
    pass

# 测试
two_sum([2, 7, 11, 15], 9)  # 应该返回 [0, 1]

题目2:合并两个有序数组

将两个有序数组合并成一个有序数组。

Python
def merge_sorted(arr1, arr2):
    """
    伪代码:
    1. 创建结果数组
    2. 用两个指针分别指向两个数组的开头
    3. 比较指针所指元素,将较小的放入结果
    4. 移动较小元素所在数组的指针
    5. 重复直到一个数组遍历完
    6. 将另一个数组剩余元素加入结果
    """
    # 你的代码
    pass

# 测试
merge_sorted([1, 3, 5], [2, 4, 6])  # [1, 2, 3, 4, 5, 6]

题目3:有效的括号

给定一个只包含括号的字符串,判断括号是否有效。

Python
def is_valid_parentheses(s):
    """
    伪代码:
    1. 用栈来存储左括号
    2. 遍历字符串:
        如果是左括号,入栈
        如果是右括号:
            如果栈为空,无效
            弹出栈顶,检查是否匹配
    3. 最后栈应该为空
    """
    # 你的代码
    pass

# 测试
is_valid_parentheses("()[]{}")  # True
is_valid_parentheses("([)]")    # False

练习2:数据处理(3-5天)

题目4:统计词频

给定一段文本,统计每个单词出现的次数。

Python
def word_frequency(text):
    """
    伪代码:
    1. 将文本转换为小写
    2. 分割成单词列表
    3. 用字典统计每个单词出现次数
    4. 返回字典
    """
    # 你的代码
    pass

# 测试
text = "Hello world hello Python"
word_frequency(text)  # {'hello': 2, 'world': 1, 'python': 1}

题目5:查找共同好友

给定两个字典表示用户的好友列表,找出共同好友。

Python
def common_friends(user1_friends, user2_friends):
    """
    伪代码:
    1. 将两个列表转换为集合
    2. 求集合的交集
    3. 返回交集列表
    """
    # 你的代码
    pass

# 测试
user1 = {"Alice": ["Bob", "Charlie", "David"]}
user2 = {"Bob": ["Alice", "Charlie", "Eve"]}
common_friends(user1["Alice"], user2["Bob"])  # ["Charlie"]

练习3:文件操作(5-7天)

题目6:CSV处理器

读取CSV文件,计算某列的平均值。

Python
def csv_average(filename, column_name):
    """
    伪代码:
    1. 打开CSV文件
    2. 读取表头,找到目标列的索引
    3. 遍历每一行,累加目标列的值
    4. 计算平均值
    5. 返回结果
    """
    # 你的代码
    pass

题目7:日志分析器

分析日志文件,统计每小时的访问次数。

Python
def analyze_log(log_file):
    """
    伪代码:
    1. 打开日志文件
    2. 用正则提取时间戳
    3. 按小时统计访问次数
    4. 返回统计结果
    """
    # 你的代码
    pass

🔍 调试思维训练

调试步骤

Text Only
1. 复现问题
   - 什么情况下出现bug?
   - 能稳定复现吗?

2. 定位问题
   - 用print输出中间结果
   - 缩小问题范围

3. 分析问题
   - 为什么会出现这个问题?
   - 我的假设哪里错了?

4. 解决问题
   - 修改代码
   - 验证修复

5. 预防问题
   - 为什么会犯这个错误?
   - 下次如何避免?

练习8:找出bug

下面代码有bug,找出并修复:

Python
def find_duplicates(arr):
    """找出数组中的重复元素"""
    duplicates = []
    for i in range(len(arr)):
        for j in range(i + 1, len(arr)):
            if arr[i] == arr[j]:
                duplicates.append(arr[i])
    return duplicates

# 测试
print(find_duplicates([1, 2, 2, 3, 3, 3]))  # 期望: [2, 3]
# 实际输出: [2, 3, 3] - 3出现了两次!

思考过程

Text Only
1. 复现:输入[1,2,2,3,3,3],输出[2,3,3]
2. 定位:3被添加了两次
3. 分析:当i指向第一个3时,j会指向第二个和第三个3,导致重复添加
4. 解决:用set去重,或修改逻辑
5. 预防:考虑边界情况

修复

Python
def find_duplicates(arr):
    """找出数组中的重复元素"""
    seen = set()
    duplicates = set()

    for num in arr:
        if num in seen:
            duplicates.add(num)
        seen.add(num)

    return list(duplicates)


✅ 阶段检查

完成以下检查,确认你掌握了编程思维:

  • 能不查资料,独立写出伪代码
  • 能根据伪代码翻译成正确代码
  • 能画出问题的逻辑流程图
  • 能考虑边界条件
  • 能独立调试简单bug

📚 下一步

完成编程思维训练后,进入 02-手写代码练习计划.md


记住:编程思维是内功,语法只是招式。内功深厚,招式自然流畅! 💪