GESP C++ 八级考试大纲知识点梳理系列文章:
在 GESP 八级考试中,最后一项考点是对 算法优化 的综合考察。这不仅仅是学会某个具体的算法,更是要求我们具备一种 “多想一步” 的思维能力:当暴力解法行不通时,如何通过数学、数据结构或算法策略来提升效率,把 $O(N^2)$ 优化到 $O(N \log N)$ 甚至 $O(N)$。
考纲要求: (8) 算法优化。理解不同方法求解一个问题在时间复杂度和空间复杂度上的差异,理解使用数学知识辅助求解问题的技巧(如可以用循环求出等差数列的和,也可以用数学公式求出等差数列的和),掌握一般的算法优化技巧。
本人也是边学、边实验、边总结,且对考纲深度和广度的把握属于个人理解。因此本文更多的不是一个教程,而是个人知识梳理,如有遗漏、疏忽,欢迎指正、交流。
本文将从三个维度来拆解常见的优化技巧:数学优化、数据结构优化 和 算法策略优化。
数学是算法的灵魂。很多看似复杂的循环,背后往往隐藏着简单的数学公式或性质。
这是考纲中直接提到的例子:求等差数列的和。
for 循环累加,时间复杂度 $O(N)$。这类优化在 几何计算(如多边形面积)、排列组合(如 $C_n^m$ 公式计算)中非常常见。
在 区间查询 和 区间修改 问题中,前缀和与差分是神器。
问题描述:给定一个包含 $N$ 个元素的数组 $A$,有 $M$ 次询问,每次询问给定区间 $[L, R]$,求该区间内所有元素的和。
for 循环从 $L$ 遍历到 $R$ 进行累加。问题描述:给定数组 $A$,有 $M$ 次操作,每次操作将区间 $[L, R]$ 内的所有数都加上 $v$。最后输出修改后的数组。
for 循环把 $A[L] \sim A[R]$ 一个个加上 $v$。核心原理:
优化操作:
当我们需要将区间 $[L, R]$ 内的所有数加上 $v$ 时,不需要遍历修改,只需修改 $D$ 数组的两个点:
D[L] += v:D[R+1] -= v:如何应用(还原结果):
D[L] += v 和 D[R+1] -= v,单次耗时 $O(1)$。A[i] = A[i-1] + D[i] (从 $1$ 到 $N$ 遍历一次)。选择合适的容器,能让代码事半功倍。
vector 或数组中遍历查找。std::set (去重/查找) 或 std::map (统计/映射)。unordered_map,均摊甚至可以到 $O(1)$(但要注意哈希冲突和常数)。sort 整个数组,然后取前 $K$ 个。x,堆顶元素为 min_val。当数学公式和数据结构都救不了你时,就需要改变算法本身的策略。
双指针通常用于将嵌套循环的 $O(N^2)$ 优化为 $O(N)$。
target。target。$O(N^2)$。A[L] + A[R] < target,说明和小了,$L++$。A[L] + A[R] > target,说明和大了,$R–$。二分不仅能查数,还能查 “答案”。
mid,然后写一个 check(mid) 函数判断这个答案是否合法。check(mid) 为真,尝试更好的;否则尝试更保守的。这是一个教科书级的优化案例,体现了从“暴力”到“数学”再到“DP”的完整进化。
问题:给定数组 A,求一个连续子数组,使得其和最大。
max(左边最大, 右边最大, 跨越中间最大)。current_sum。如果 current_sum 变成负数了,把它置为 0(因为负数只会拖累后面的和)。记录过程中的最大值。算法优化没有定式,但有迹可循。在考场上遇到难题(尤其是 TLE 时),请按以下顺序思考优化方向:
通过八级的学习,我们不仅仅是在学 Coding,更是在学 Problem Solving。希望大家在 GESP 考试中都能游刃有余,写出既“快”又“省”的满分代码!
所有代码已上传至Github:https://github.com/lihongzheshuai/yummy-code
GESP 学习专题站:GESP WIKI
“luogu-”系列题目可在洛谷题库进行在线评测。
“bcqm-”系列题目可在编程启蒙题库进行在线评测。
欢迎加入:Java、C++、Python技术交流QQ群(982860385),大佬免费带队,有问必答
欢迎加入:C++ GESP/CSP认证学习QQ频道,考试资源总结汇总
欢迎加入:C++ GESP/CSP学习交流QQ群(688906745),考试认证学员交流,互帮互助
GESP C++ 八级考试大纲知识点梳理系列文章:
在 GESP 八级考试中,最后一项考点是对 算法优化 的综合考察。这不仅仅是学会某个具体的算法,更是要求我们具备一种 “多想一步” 的思维能力:当暴力解法行不通时,如何通过数学、数据结构或算法策略来提升效率,把 $O(N^2)$ 优化到 $O(N \log N)$ 甚至 $O(N)$。
考纲要求: (8) 算法优化。理解不同方法求解一个问题在时间复杂度和空间复杂度上的差异,理解使用数学知识辅助求解问题的技巧(如可以用循环求出等差数列的和,也可以用数学公式求出等差数列的和),掌握一般的算法优化技巧。
本人也是边学、边实验、边总结,且对考纲深度和广度的把握属于个人理解。因此本文更多的不是一个教程,而是个人知识梳理,如有遗漏、疏忽,欢迎指正、交流。
本文将从三个维度来拆解常见的优化技巧:数学优化、数据结构优化 和 算法策略优化。
数学是算法的灵魂。很多看似复杂的循环,背后往往隐藏着简单的数学公式或性质。
这是考纲中直接提到的例子:求等差数列的和。
for 循环累加,时间复杂度 $O(N)$。这类优化在 几何计算(如多边形面积)、排列组合(如 $C_n^m$ 公式计算)中非常常见。
在 区间查询 和 区间修改 问题中,前缀和与差分是神器。
问题描述:给定一个包含 $N$ 个元素的数组 $A$,有 $M$ 次询问,每次询问给定区间 $[L, R]$,求该区间内所有元素的和。
for 循环从 $L$ 遍历到 $R$ 进行累加。问题描述:给定数组 $A$,有 $M$ 次操作,每次操作将区间 $[L, R]$ 内的所有数都加上 $v$。最后输出修改后的数组。
for 循环把 $A[L] \sim A[R]$ 一个个加上 $v$。核心原理:
优化操作:
当我们需要将区间 $[L, R]$ 内的所有数加上 $v$ 时,不需要遍历修改,只需修改 $D$ 数组的两个点:
D[L] += v:D[R+1] -= v:如何应用(还原结果):
D[L] += v 和 D[R+1] -= v,单次耗时 $O(1)$。A[i] = A[i-1] + D[i] (从 $1$ 到 $N$ 遍历一次)。选择合适的容器,能让代码事半功倍。
vector 或数组中遍历查找。std::set (去重/查找) 或 std::map (统计/映射)。unordered_map,均摊甚至可以到 $O(1)$(但要注意哈希冲突和常数)。sort 整个数组,然后取前 $K$ 个。x,堆顶元素为 min_val。当数学公式和数据结构都救不了你时,就需要改变算法本身的策略。
双指针通常用于将嵌套循环的 $O(N^2)$ 优化为 $O(N)$。
target。target。$O(N^2)$。A[L] + A[R] < target,说明和小了,$L++$。A[L] + A[R] > target,说明和大了,$R–$。二分不仅能查数,还能查 “答案”。
mid,然后写一个 check(mid) 函数判断这个答案是否合法。check(mid) 为真,尝试更好的;否则尝试更保守的。这是一个教科书级的优化案例,体现了从“暴力”到“数学”再到“DP”的完整进化。
问题:给定数组 A,求一个连续子数组,使得其和最大。
max(左边最大, 右边最大, 跨越中间最大)。current_sum。如果 current_sum 变成负数了,把它置为 0(因为负数只会拖累后面的和)。记录过程中的最大值。算法优化没有定式,但有迹可循。在考场上遇到难题(尤其是 TLE 时),请按以下顺序思考优化方向:
通过八级的学习,我们不仅仅是在学 Coding,更是在学 Problem Solving。希望大家在 GESP 考试中都能游刃有余,写出既“快”又“省”的满分代码!
所有代码已上传至Github:https://github.com/lihongzheshuai/yummy-code
GESP 学习专题站:GESP WIKI
“luogu-”系列题目可在洛谷题库进行在线评测。
“bcqm-”系列题目可在编程启蒙题库进行在线评测。
欢迎加入:Java、C++、Python技术交流QQ群(982860385),大佬免费带队,有问必答
欢迎加入:C++ GESP/CSP认证学习QQ频道,考试资源总结汇总
欢迎加入:C++ GESP/CSP学习交流QQ群(688906745),考试认证学员交流,互帮互助