MaximizeSum程序性能优化求助:大序列快速计算最大和
问题分析与优化方案
原程序用于计算移除非首尾元素最大化总点数,但存在指数级时间复杂度、IEnumerable频繁遍历开销、不必要异步操作三大问题,导致无法处理100个元素的序列。以下是针对性优化方案:
核心问题拆解
- 暴力递归的指数级复杂度:原代码枚举所有移除顺序,时间复杂度为O((n-2)!),n=100时完全无法计算。
- IEnumerable操作低效:
Count()、ElementAt()、RemoveAt()均为O(n)时间操作,每次递归多次遍历序列,进一步恶化性能。 - 异步滥用:所有操作均为CPU密集型,异步调度反而增加额外开销。
优化思路:动态规划(戳气球变种)
该问题可转化为类似"戳气球"的动态规划问题,通过状态缓存将时间复杂度降至O(n³),空间复杂度O(n²),轻松处理n=100的场景。
状态定义
dp[i][j]:移除原序列中索引i到j之间的所有元素(不包含i和j)的最大总sum之和。
状态转移
- 当
j <= i+1时,dp[i][j] = 0(无元素可移除)。 - 当
j > i+1时,选择最后一个被移除的元素k(i < k < j),此时移除k的sum为arr[i] + arr[k] + arr[j](k的邻居为i和j),总sum为:dp[i][j] = max(dp[i][k] + dp[k][j] + arr[i] + arr[k] + arr[j])
最终结果计算
遍历所有可能的最后剩余中间元素k,总点数为:
总点数 = dp[0][k] + dp[k][n-1] + arr[0] + arr[k] + arr[n-1]
取所有k对应的最大值即为答案。
优化后代码实现
public interface ISolver<T> { Task<T> SolveAsync(IEnumerable<T> sequence); } public class Solver : ISolver<short> { public async Task<short> SolveAsync(IEnumerable<short> sequence) { var arr = sequence.ToArray(); int n = arr.Length; if (n == 3) return (short)(arr[0] + arr[1] + arr[2]); if (n < 3) throw new ArgumentException("序列长度至少为3"); short[,] dp = new short[n, n]; // 按子序列长度从小到大计算 for (int len = 2; len < n; len++) { for (int i = 0; i + len < n; i++) { int j = i + len; dp[i, j] = 0; for (int k = i + 1; k < j; k++) { short current = (short)(dp[i, k] + dp[k, j] + arr[i] + arr[k] + arr[j]); if (current > dp[i, j]) { dp[i, j] = current; } } } } short maxTotal = 0; for (int k = 1; k < n - 1; k++) { short total = (short)(dp[0, k] + dp[k, n - 1] + arr[0] + arr[k] + arr[n - 1]); if (total > maxTotal) { maxTotal = total; } } return await Task.FromResult(maxTotal); } }
代码说明
- 数组转换:将IEnumerable转为数组,实现O(1)时间元素访问,避免频繁遍历。
- 动态规划填充:按子序列长度从小到大计算,确保子状态先于父状态完成计算。
- 异步兼容:用
Task.FromResult包装结果,保持与原接口一致,无额外异步开销。 - 性能提升:n=100时仅需毫秒级计算,相比原代码性能提升数个数量级。
内容的提问来源于stack exchange,提问作者Gqrsw
相关产品推荐
相关产品推荐

