LeetCode 813 最大平均值和的分组[动态规划 前缀和] HERODING的LeetCode之路

LeetCode 813 最大平均值和的分组[动态规划 前缀和] HERODING的LeetCode之路_第1张图片

解题思路:
一道非常有有参考价值的动态规划题型,是前缀和和动态规划的结合,首先计算前缀和,便于求解dp时计算区间的和,对于dp数组,dp[i][j]表示对于长度为i的序列,将其分为j组所得到的最大平均值,那么就可以开始遍历了,首先遍历整个序列,i为当前遍历的序列的长度,对于当前的长为i的序列,遍历K,即将序列分为1——K组,对于每个分组,状态转移方程为:dp[i][k] = max(dp[i][k], dp[j][k - 1] + t),t表示序列中j——i子序列的平均值,代码如下:

class Solution {
public:
    double largestSumOfAverages(vector<int>& nums, int K) {
        int n = nums.size();
        vector<vector<double>> dp(n + 1, vector<double>(K + 1));
        vector<double> prefix(n + 1);
        for(int i = 1; i <= n; i ++) {
            prefix[i] = prefix[i - 1] + nums[i - 1];
        }
        // 遍历序列
        for(int i = 1; i <= n; i ++) {
            dp[i][1] = prefix[i] / i;
        }
        for(int k = 2; k <= K; k ++) {
            for(int i = k; i <= n; i ++) {
                // 分割区间
                for(int j = 1; j < i; j ++) {
                    double t = (prefix[i] - prefix[j]) / (i - j);
                    dp[i][k] = max(dp[i][k], dp[j][k - 1] + t); 
                }
            }
        }
        return dp[n][K];
    }
};

观察发现由于dp[i][k]只用到k-1的数据,因此可以优化dp数组为一维数组,注意序列长度要从大到小遍历,代码如下:

class Solution {
public:
    double largestSumOfAverages(vector<int>& nums, int K) {
        int n = nums.size();
        vector<double> dp(n + 1);
        vector<double> prefix(n + 1);
        for(int i = 1; i <= n; i ++) {
            prefix[i] = prefix[i - 1] + nums[i - 1];
        }
        // 遍历序列
        for(int i = 1; i <= n; i ++) {
            dp[i] = prefix[i] / i;
        }
        for(int k = 2; k <= K; k ++) {
            for(int i = n; i >= k; i --) {
                // 分割区间
                for(int j = 1; j < i; j ++) {
                    double t = (prefix[i] - prefix[j]) / (i - j);
                    dp[i] = max(dp[i], dp[j] + t); 
                }
            }
        }
        return dp[n];
    }
};

你可能感兴趣的:(LeetCode,leetcode,动态规划,算法,c++,数据结构)