求助:求最小化总代价的序列中间元素删除O(n³)复杂度算法
高效解法:区间动态规划(O(n³) 时间复杂度)
嘿,这个问题其实是经典的区间动态规划场景,暴力枚举删除顺序的阶乘级复杂度肯定没法处理稍大的n,咱们直接用DP来解决,正好能达到你要的O(n³)时间复杂度。我给你一步步拆解思路:
1. 先明确DP状态的定义
咱们定义 dp[i][j] 表示删除区间 [i, j] 内所有中间元素(最终只保留 a[i] 和 a[j])时的最小总代价。这里有几个边界情况:
- 如果
i == j:没有元素可删,代价为0 - 如果
j == i+1:中间没有元素,代价也为0
2. 推导状态转移方程
核心思路是:对于区间 [i, j],咱们假设最后一个被删除的元素是 k(i < k < j)。这时候,当把 [i,k] 和 [k,j] 内的中间元素都删完后,k 的左右邻居就只剩下 a[i] 和 a[j] 了,所以删除 k 的代价就是 a[i] * a[j]。
那整个区间 [i,j] 的最小代价,就是处理 [i,k] 的最小代价 + 处理 [k,j] 的最小代价 + 删除 k 的代价。所以转移方程是:
dp[i][j] = min(dp[i][k] + dp[k][j] + a[i] * a[j]) ,其中 i < k < j
3. 初始化与计算顺序
- 初始化:所有
dp[i][i] = 0,dp[i][i+1] = 0,这些都是无需删除元素的情况。 - 计算顺序:必须按区间长度从小到大计算。因为长区间的解依赖于更短的子区间解,所以我们从长度为3的区间开始(长度1、2的已经初始化),直到覆盖整个序列的长度n。
举个直观的小例子
比如序列 A = [1,2,3,4],我们要算 dp[0][3](假设数组是0索引):
- 可选的k是1和2:
- 当k=1时:
dp[0][1] + dp[1][3] + 1*4 = 0 + (dp[1][2]+dp[2][3]+2*4) +4 = 0 + (0+0+8)+4 = 12 - 当k=2时:
dp[0][2] + dp[2][3] +1*4 = (dp[0][1]+dp[1][2]+1*3)+0+4 = (0+0+3)+4 =7
所以dp[0][3] = min(12,7) =7,这就是删除所有中间元素的最小总代价。
- 当k=1时:
复杂度验证
- 区间长度有O(n)种(从3到n)
- 每个长度对应的起始点i有O(n)种选择
- 每个区间
[i,j]对应的k有O(n)种可能
三者相乘就是O(n³),完全符合你的要求。
伪代码实现参考
n = len(A) # 初始化n×n的DP数组,默认值为0 dp = [[0]*n for _ in range(n)] # 遍历区间长度,从3开始到n for length in range(3, n+1): # 遍历所有可能的起始索引i for i in range(n - length + 1): j = i + length - 1 dp[i][j] = float('inf') # 先设为无穷大,再找最小值 # 遍历所有可能的最后删除元素k for k in range(i+1, j): current_cost = dp[i][k] + dp[k][j] + A[i] * A[j] if current_cost < dp[i][j]: dp[i][j] = current_cost # 最终答案就是删除整个序列中间元素的最小代价 print(dp[0][n-1])
这个方案的核心是把大问题拆解成子区间的最优解,用DP缓存结果避免重复计算,比暴力解法高效太多,完全能处理中等规模的n值。
内容的提问来源于stack exchange,提问作者Avaneesh Kumar
相关产品推荐
相关产品推荐

