算法小练习之分隔数组以得到最大和

152 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 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、执行结果

image.png

好了、本期就先介绍到这里,有什么需要交流的,大家可以随时私信我。😊