持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第29天,点击查看活动详情
1、前言
每天一个算法小练习,本篇使用Java实现。
2、题目描述
给你一个整数数组 arr,请你将该数组分隔为长度最多为 k 的一些(连续)子数组。分隔完成后,每个子数组的中的所有值都会变为该子数组中的最大值。返回将数组分隔变换后能够得到的元素最大和。
注意,原数组和分隔后的数组对应顺序应当一致,也就是说,你只能选择分隔数组的位置而不能调整数组中的顺序。
2.1、示例1
输入:arr = [1,15,7,9,2,5,10], k = 3
输出:84
解释:
因为 k=3 可以分隔成 [1,15,7] [9] [2,5,10],结果为 [15,15,15,9,10,10,10],和为 84,是该数组所有分隔变换后元素总和最大的。
若是分隔成 [1] [15,7,9] [2,5,10],结果就是 [1, 15, 15, 15, 10, 10, 10] 但这种分隔方式的元素总和(76)小于上一种。
2.2、示例2
输入:arr = [1,4,1,5,7,3,6,1,9,9,3], k = 4
输出:83
2.3、示例3
输入:arr = [1], k = 1
输出:1
3、解题思路
1、动态规划,与最低票价、青蛙跳台阶这些问题套路类似。
2、暴力搜索,递归求解。
3.1、实现代码
/**
* 动态规划求解
* @param arr
* @param k
* @return
*/
public int maxSumAfterPartitioning(int[] arr, int k) {
//dp数组含义:dp[i] = sum, 表示前i个元素进行合理分割能得到的最大值为sum
int[] dp = new int[arr.length];
int max = arr[0];
dp[0] = arr[0];
//状态转移方程:dp[i] = max(dp[i-k]+k*(arr[i-k+1...i]).....dp[i-1]+1*arr[i])
for (int i = 1; i < arr.length; i++) {
int maxsum = 0;
max = arr[i];
for (int j = 1; j < k + 1; j++) {
int sum = 0;
//更新最大值
max = Math.max(max, arr[i - j + 1]);
//更新所有可能的最大值
if (i - j < 0) {
sum = max * (i + 1);
maxsum = Math.max(maxsum, sum);
break;
} else {
sum = dp[i - j] + max * j;
maxsum = Math.max(maxsum, sum);
}
}
dp[i] = maxsum;
}
//答案就是dp[arr.size()-1]
return dp[arr.length - 1];
}
3.2、执行结果
好了、本期就先介绍到这里,有什么需要交流的,大家可以随时私信我。😊