Skip to content

问题解决模式

解题四步法

Step 1: 理解问题

在开始编码之前,确保你完全理解问题:

  • 输入是什么? 类型、范围、约束
  • 输出是什么? 期望的格式和类型
  • 有什么特殊要求? 时间限制、空间限制
  • 边界情况? 空输入、大规模输入、重复元素

💡 提示

如果不确定,要主动提问。这展示了你的沟通能力。

Step 2: 暴力解法

先想出一个能工作的解法,即使它不是最优的:

  1. 明确暴力的方法是什么
  2. 评估其时间和空间复杂度
  3. 这是你的 baseline,后续会优化

Step 3: 优化

思考优化的方向:

  • 空间换时间 - 使用额外的数据结构
  • 时间换空间 - 预处理、预计算
  • 算法改进 - 分治、动态规划、贪心
  • 数据结构改进 - 用哈希表替代数组、用堆优化

Step 4: 代码实现

  • 保持代码清晰和模块化
  • 使用有意义的变量名
  • 适当注释关键逻辑

常见问题模式

1. 两指针模式

适用于有序数组链表问题。

python
def two_pointers(arr, target):
    left, right = 0, len(arr) - 1
    while left < right:
        current = arr[left] + arr[right]
        if current == target:
            return [left, right]
        elif current < target:
            left += 1
        else:
            right -= 1
    return []

典型场景

  • 两数之和(有序数组)
  • 三数之和
  • 验证回文串

2. 滑动窗口

适用于子数组/子串问题。

python
def sliding_window(s, k):
    window = {}
    left = 0
    for right in range(len(s)):
        # 扩展窗口
        window[s[right]] = window.get(s[right], 0) + 1

        # 收缩窗口
        while window[s[right]] > k:
            window[s[left]] -= 1
            left += 1
    return left

典型场景

  • 最大子数组长度(限制重复元素个数)
  • 字符串排列
  • 最小覆盖子串

3. 二分查找变体

适用于有序数据的搜索问题。

python
def binary_search(nums, target):
    left, right = 0, len(nums) - 1
    while left <= right:
        mid = left + (right - left) // 2
        if nums[mid] == target:
            return mid
        elif nums[mid] < target:
            left = mid + 1
        else:
            right = mid - 1
    return -1

典型场景

  • 搜索旋转排序数组
  • 寻找边界(第一个/最后一个位置)
  • 寻找峰值元素

4. 递归与回溯

适用于组合、排列、子集问题。

python
def backtrack(result, path, choices):
    if is_valid_complete(path):
        result.append(path.copy())
        return

    for choice in choices:
        if is_promising(choice):
            path.append(choice)
            backtrack(result, path, remaining_choices(choice))
            path.pop()

典型场景

  • 全排列
  • 组合总和
  • N 皇后问题

5. 广度优先搜索 (BFS)

适用于层次遍历、最短路径问题。

python
from collections import deque

def bfs(graph, start):
    visited = set()
    queue = deque([start])
    visited.add(start)

    while queue:
        node = queue.popleft()
        for neighbor in graph[node]:
            if neighbor not in visited:
                visited.add(neighbor)
                queue.append(neighbor)

典型场景

  • 二叉树层序遍历
  • 图的最短路径
  • 迷宫问题

6. 深度优先搜索 (DFS)

适用于遍历、连通性、路径问题。

python
def dfs(graph, node, visited):
    visited.add(node)
    for neighbor in graph[node]:
        if neighbor not in visited:
            dfs(graph, neighbor, visited)

典型场景

  • 二叉树遍历(前/中/后序)
  • 图的连通分量
  • 岛屿数量问题

7. 动态规划

适用于最优子结构问题。

解题步骤

  1. 确定 DP 状态(dp[i] 含义)
  2. 推导状态转移方程
  3. 确定初始值
  4. 确定遍历顺序
python
# 一维 DP 示例:爬楼梯
def climb_stairs(n):
    if n <= 2:
        return n
    dp = [0] * (n + 1)
    dp[1], dp[2] = 1, 2
    for i in range(3, n + 1):
        dp[i] = dp[i-1] + dp[i-2]
    return dp[n]

# 空间优化
def climb_stairs_optimized(n):
    if n <= 2:
        return n
    prev, curr = 1, 2
    for i in range(3, n + 1):
        prev, curr = curr, prev + curr
    return curr

典型场景

  • 斐波那契数列
  • 背包问题
  • 最长公共子序列

8. 分治法

将问题分解为子问题,解决子问题,然后合并

python
def divide_conquer(problem):
    if is_base_case(problem):
        return solve_base(problem)

    sub_problems = split(problem)
    sub_results = [divide_conquer(sub) for sub in sub_problems]
    return merge(sub_results)

典型场景

  • 归并排序
  • 快速排序
  • 最近点对问题

复杂度速查

数据结构操作时间复杂度
数组访问、查找O(1)、O(n)
数组插入、删除O(n)
链表访问O(n)
链表头部插入/删除O(1)
哈希表查找、插入、删除O(1) 平均
二叉搜索树查找、插入、删除O(log n) 平均
查找最大/最小O(1)
插入、删除O(log n)
算法时间复杂度
冒泡/插入/选择排序O(n^2)
归并/快速排序O(n log n)
堆排序O(n log n)
计数/桶排序O(n + k)
二分查找O(log n)
图遍历 BFS/DFSO(V + E)

面试技巧

  1. 不要急于编码 - 先思考清楚再动手
  2. 边想边说 - 展示你的思维过程
  3. 寻求确认 - "这样理解对吗?"
  4. 考虑边界 - 空输入、极端情况
  5. 多种方案 - 先说简单方案,再优化

基于 VitePress 构建