如何写出算法题?-算法思维

算法思维过程

能问出这个问题?你已经走在提升算法水平的核心路上了
刷题本身只是手段,真正关键的就是「算法思维过程」。
下面总结给你一套可执行的“算法思维训练体系”,直接拿去用:


? 一、转变思维方式:从“找答案”转为“学过程”

错题是宝藏,做不出来没关系,核心是:

  • 想清楚:我为什么会卡住?
  • 是因为思路没拓展?不会拆分?不了解数据结构?对复杂度没概念?

? 建议: 每次遇到新题,至少逼自己想10分钟,用以下问题问自己:

1. 有没有最直接的暴力解?(不要怕,先写出来)
2. 会不会超时?大概什么复杂度?
3. 有没有能拆分成两个部分的结构?(分治、分组)
4. 有没有能用哈希表、双指针、前缀和、排序优化的地方?
5. 这题和我做过的哪道题像?能借鉴吗?

? 二、每学一种算法,都给自己留“刻意练习”任务

比如:

学到的算法刻意练习方向
哈希表练「两数之和」、「四数之和」、「异或」、「字符统计」
双指针练「有序数组去重」、「盛水最多的容器」、「三数之和」
前缀和、差分练「区间和」、「二维前缀和」、「差分数组」
滑动窗口练「最小子串覆盖」、「最长无重复子串」、「滑动最大值」
递归 & 回溯练「全排列」、「组合」、「子集」、「N皇后」
二分练「搜索区间」、「求平方根」、「最大最小问题」

? 核心在于:每种方法,找到 3-5 道有代表性的题目,死磕,做到:

  • 看完题,第一反应就想起这招
  • 练出手感

? 三、锻炼“建模”的能力

很多题目是文字游戏,关键在于“把问题抽象成熟悉的模型”:

题目场景建模思路
找满足条件的组合转换成「nSum」模型
连续区间内最大/最小值想到「前缀和」「单调队列」「滑动窗口」
涉及顺序的问题想到「栈」「队列」「递归」
统计方案数想「dp」有没有必要
树、图的遍历立刻往「BFS」「DFS」靠

? 四、刷题顺序建议(重要)

先刷经典题,锻炼你对这些思维的掌控力:

1. 数组:两数之和、三数之和、盛水容器
2. 哈希表:有效的字母异位词、四数相加
3. 双指针:有序数组去重、最小覆盖子串
4. 栈/队列:有效括号、每日温度
5. 动态规划:爬楼梯、背包、最长子序列
6. 二分:搜索区间、旋转数组
7. 前缀和 & 差分:区间和,子数组和为K
8. 图:BFS、DFS模板题

? 五、写题解/反思(形成完整闭环)

✅ 你做一道题,试图给“未来的自己”写一份思路笔记:

1. 题目的核心是啥?本质模型?
2. 我一开始想到的暴力解法是什么?为什么不行?
3. 最终解法用了啥优化技巧?
4. 这个技巧能迁移到哪里?

? 比如:

  • 这题让我学会了「哈希表统计组合次数」
  • 类似的还有「两数之和」「三数之和」等问题

? 六、推荐工具/训练资源

类型推荐
刷题平台力扣(LeetCode)、AcWing(有中文讲解)
题单LeetCode Top 100、经典算法分类题单
《剑指 Offer》、《程序员代码面试指南》
视频哔哩哔哩 左神、花花酱算法、代码随想录
社区公众号「代码随想录」、力扣官方讨论区

总结:真正的算法高手都是这样炼成的

  • 多问自己为什么:卡住时别马上看答案,先反思哪里想不到
  • 多做题型归纳:一题多解,一题带一类
  • 多总结核心模型:哈希表、前缀和、双指针……烂熟于心
  • 形成完整闭环:做、想、总结、复盘,不断内化

示例

这就是学会「算法思维过程」的关键步骤。
借鉴题目 "4Sum II"(力扣:四数之和),很经典。接下来我带你走一遍“正常人做题的思路 + 试错 + 碰壁 + 优化”的完整过程。


? 第一步:最直接的暴力思路

【想法】

题目问 (i, j, k, l) 满足 A[i] + B[j] + C[k] + D[l] == 0

  • i、j、k、l 都独立,可以四层循环,把所有可能列出来
  • 每找到一组符合的就 count++

【代码雏形】

int count = 0;
for (int i = 0; i < N; i++) {
 for (int j = 0; j < N; j++) {
 for (int k = 0; k < N; k++) {
 for (int l = 0; l < N; l++) {
 if (A[i] + B[j] + C[k] + D[l] == 0) count++;
 }
 }
 }
}

【试错点】

  • 时间复杂度 O(N^4)
  • N最大500 → 500⁴ = 6250亿次循环
  • 明显超时!暴力直接死!

? 第二步:尝试优化——分组 + 预处理

【灵感来源】

  • 想到:A[i] + B[j] + C[k] + D[l] == 0 可以拆成两部分
  • (A[i] + B[j]) + (C[k] + D[l]) == 0
  • 如果能先算出 A[i] + B[j] 所有可能,然后去查找 -(C[k] + D[l]),问题会简单很多!

【核心突破】

  • 构建 unordered_map<int, int>,key 是 A[i] + B[j] 的和,value 是出现的次数(因为可能有重复)
  • 再枚举 C[k] + D[l],每算一个就看 -(C[k] + D[l]) 是否在 map 里

? 第三步:算算复杂度

  • A[i] + B[j] 枚举一遍:O(N^2)
  • C[k] + D[l] 再枚举一遍:O(N^2)
  • 查询 map 是 O(1)
  • 总复杂度 O(N^2) + O(N^2) = O(N^2),完美解决500的数据量!

? 第四步:模拟试错版本

假设:

A = [1, 2], B = [-2, -1], C = [-1, 2], D = [0, 2]

先处理 A + B:

  • 1 + (-2) = -1
  • 1 + (-1) = 0
  • 2 + (-2) = 0
  • 2 + (-1) = 1

结果:

sumAB = {
 -1: 1,
 0: 2,
 1: 1
}

再处理 C + D 并查 map:

  • -1 + 0 = -1 → 看 1 是否在 sumAB
  • -1 + 2 = 1 → 看 -1 是否在 sumAB
  • 2 + 0 = 2 → 看 -2 是否在 sumAB
  • 2 + 2 = 4 → 看 -4 是否在 sumAB

查到的部分:

  • -1 在 sumAB,有1个 → 计数 +1
  • 1 在 sumAB,有1个 → 计数 +1

最终答案:2


第五步:总结一般解题套路(非常重要)

阶段做法典型思路
1. 暴力尝试四层循环,发现复杂度炸了暴力总是第一想法
2. 分组降维发现可以 (A+B)(C+D) 分组分组思想
3. 哈希优化用 map 统计出现次数,反查匹配空间换时间
4. 时间复杂度优化到 O(N^2)可接受
5. 通用套路多数求和问题可尝试「分组 + 哈希表」nSum问题

? 这题的本质

  • 本质上是「四数之和等于0」的计数问题
  • 通用解法:前一半枚举进哈希表,后一半直接查找匹配
  • 扩展题目也能用类似思路做
作者:竹沁原文地址:https://www.cnblogs.com/y-cw/p/18823747

%s 个评论

要回复文章请先登录注册