题目描述:
https://leetcode.com/problems/largest-sum-of-averages/submissions/
题目大意:
讲一个整数数组分成连续的K个子数组,问这K个子数组的平均值之和的最大值是多少?
解决思路:
就相当于在len(A)长度的数组中存在的len(A)-1个间隔中插入K-1个“隔板”使得分隔开来的K个连续子数组平均值之和最大。
可以使用回溯进行遍历。这里注意到当前几个隔板放置好后,余下的数组长度和隔板数量对应的子问题答案是会在回溯过程中被反复求解的,也就是出现了重复子问题,可以使用动态规划,即记忆化回溯。使用一个memory字典记录(长度,隔板数目)对应的子问题的解
另一个思路是直接使用dp矩阵进行求解。思路类似矩阵相乘次数最少那道题目(后续补充)
python 记忆化回溯代码:
class Solution(object):
def largestSumOfAverages(self, A, K):
"""
:type A: List[int]
:type K: int
:rtype: float
"""
memory = {}
res = [0]
self.helper(A,K,memory,0,res)
print(memory)
return res[0]
def helper(self,A,K,memory,now_sum,res):
if K>len(A):
return 0
elif K==len(A):
res[0] = max(res[0],now_sum + sum(A))
return sum(A)
elif K<len(A) and K==1:
res[0] = max(res[0],now_sum + float(sum(A))/len(A))
return float(sum(A))/len(A)
else:
if (len(A),K) in memory:
res[0] = max(res[0],now_sum + memory[(len(A),K)])
else:
memory[(len(A),K)] = -1
for i in range(0,len(A)-1):
memory[(len(A),K)] = max(memory[(len(A),K)],float(sum(A[:i+1]))/(i+1)+self.helper(A[i+1:],K-1,memory,now_sum + float(sum(A[:i+1]))/(i+1),res))
res[0] = max(res[0],now_sum + memory[(len(A),K)])
return memory[(len(A),K)]
二维dp矩阵python代码:
class Solution(object):
def largestSumOfAverages(self, A, K):
"""
:type A: List[int]
:type K: int
:rtype: float
"""
def dp(A, K):
dp = [[0] * len(A) for _ in range(K)]
for j in range(len(A)):
dp[0][j] = self.mean(A[:j + 1])
for k in range(1, K):
for j in range(k, len(A)):
for i in range(j):
dp[k][j] = max(dp[k][j], dp[k - 1][i] + self.mean(A[i + 1:j + 1]))
return dp[-1][-1]
return dp(A, K)
def mean(self,L):
return float(sum(L))/len(L)