leetcode——【三个无重叠子数组的最大和】

题目

在这里插入图片描述

思路

1.暴力遍历

首先求得位置poi的k项和数组,数组长度为nums的length-k+1

		sum_arr[0] = accumulate(nums.begin(), nums.begin() + k, 0);
		for (int i = 1; i < sum_arr.size(); ++i)
			sum_arr[i] = sum_arr[i - 1] - nums[i - 1] + nums[i + k - 1];

然后进行三层遍历,第n层遍历第n/3个子数组的起始位置,暴力遍历每种情况的的子数组和,最后得到最大的输出。

class Solution {
    
    
public:
    vector<int> maxSumOfThreeSubarrays(vector<int>& nums, int k) {
    
    
        vector<int> sum_arr(nums.size() - k + 1);
        sum_arr[0] = accumulate(nums.begin(), nums.begin() + k, 0);
        for (int i = 1; i < sum_arr.size(); ++i)
            sum_arr[i] = sum_arr[i - 1] - nums[i - 1] + nums[i + k - 1];
        vector<int> result;
        int sum = 0;
        for (int i = 0; i < sum_arr.size() - k * 2; ++i)
            for (int j = i + k; j < sum_arr.size() - k; ++j)
                for (int t = j + k; t < sum_arr.size(); ++t)
                    if (sum < sum_arr[i] + sum_arr[j] + sum_arr[t]) {
    
    
                        sum = sum_arr[i] + sum_arr[j] + sum_arr[t];
                        result = {
    
    i, j, t};
                    }
        return result;
    }
};

2.滑动窗口

思路:
要计算三个无重叠子数组的最大和,我们可以枚举第三个子数组的位置,同时维护前两个无重叠子数组的最大和及其位置。
要计算两个无重叠子数组的最大和,我们可以枚举第二个子数组的位置,同时维护第一个子数组的最大和及其位置。
因此,我们首先来解决单个子数组的最大和问题,然后解决两个无重叠子数组的最大和问题,最后解决三个无重叠子数组的最大和问题。
窗口移动时,当第一个窗口的和变大后,要使用此位置的和,必然需要第二个位置的窗口也使用新窗口,当两者和比原来大时,才能更新两个子数组的开始位置。第三个窗口同理,当前两窗口和+第三窗口和大于原来时,才能更新三个子数组的位置。

class Solution {
    
    
public:
	vector<int> maxSumOfThreeSubarrays(vector<int>& nums, int k) {
    
    
		int first_sum = 0, second_sum = 0, third_sum = 0;
		int first_idx = 0, second_idx = k, second_sum_first_idx = 0;
		int first_max = 0, second_max = 0, third_max = 0;
		vector<int> result;
		for (int i = 2 * k; i < nums.size(); ++i) {
    
    
			first_sum += nums[i - 2 * k];
			second_sum += nums[i - k];
			third_sum += nums[i];
			if (i >= 3 * k - 1) {
    
    
				if (first_sum > first_max) {
    
    
					first_max = first_sum;
					first_idx = i - 3 * k + 1;
				}
				if (first_max + second_sum > second_max) {
    
    
					second_max = first_max + second_sum;
					second_sum_first_idx = first_idx;
					second_idx = i - 2 * k + 1;
				}
				if (second_max + third_sum > third_max) {
    
    
					result = {
    
     second_sum_first_idx, second_idx , i - k + 1 };
					third_max = second_max + third_sum;
				}
				first_sum -= nums[i - k * 3 + 1];
				second_sum -= nums[i - k * 2 + 1];
				third_sum -= nums[i - k + 1];
			}
		}
		return result;
	}
};

3.动态规划

核心推导:
在这里插入图片描述
i代表i+1个子数组,j代表k+j个数字,dp[i][j]代表i+1个子数组、数组长度为k+j时数组和的值。
按照递推关系,进行动态规划求解。
然后对于这个数组,dp[i][j]随着j减小开始变化时,设开始变化的位置为d,则d+1为第i+1个子数组的开始位置,然后对其位置减去k,dp[i-1][d+1-k]随着d+1-k减小开始变化时,此位置为第i个子数组的开始位置,以此类推。

class Solution {
    
    
public:
	vector<int> maxSumOfThreeSubarrays(vector<int>& nums, int k) {
    
    
		vector<vector<int>> dp(3, vector<int>(nums.size() - k + 1, 0));
		vector<int> sum_arr(nums.size() - k + 1);
		vector<int> result(3);
		sum_arr[0] = accumulate(nums.begin(), nums.begin() + k, 0);
		for (int i = 1; i < sum_arr.size(); ++i)
			sum_arr[i] = sum_arr[i - 1] - nums[i - 1] + nums[i + k - 1];
		int temp = 0;
		for (int i = 0; i < 3; ++i) {
    
    
			for (int j = i * k; j < nums.size() - k + 1; ++j) {
    
    
				if (i == 0)
					temp = sum_arr[j];
				else
					temp = dp[i - 1][j - k] + sum_arr[j];
				if (j == i * k)
					dp[i][j] = temp;
				else
					dp[i][j] = max(dp[i][j - 1], temp);
			}
		}
		int j = nums.size() - k;
		for (int i = 2; i >= 0; --i) {
    
    
			while (j != 0 && dp[i][j] == dp[i][j - 1])
				j--;
			result[i] = j;
			j = j - k;
		}
		return result;
	}
};

おすすめ

転載: blog.csdn.net/super_carry/article/details/121800601