青训营X 豆包MarsCode AI 刷题

72 阅读3分钟

题目内容:

小包非常喜欢吃甜点,他收到了一次性送来的 NN 个甜点,每个甜点都有一个对应的喜爱值。

但是这还不够!小包让小哥连续送来了 MM 次相同的 NN 个甜点,并将这些甜点首尾相接排成一排。

现在,小包面前有 (N×M)(N×M) 个排成一排的甜点,小包希望从中选择一段连续的甜点,使得这段甜点的总喜爱值最大化。

注意:尽管小包喜欢甜食,但有些甜点可能不合口味,导致其喜爱值为负数。小包至少要选择一个甜点来满足他对甜点的贪心。

输入参数

  • 整数 ( N ):表示每次送来的甜点数量。
  • 整数 ( M ):表示送来的次数。
  • 数组 data:长度为 ( N ),表示每个甜点的喜爱值。

返回结果

  • 一个整数,表示在 N×MN×M 个甜点中可以选择的连续甜点段的最大总喜爱值。

测试样例

样例1:

输入:N = 5 ,M = 1 ,data = [1, 3, -9, 2, 4]
输出:6
解释:选择甜点 [2, 4],最大总喜爱值为 6

样例2:

输入:N = 5 ,M = 3 ,data = [1, 3, -9, 2, 4]
输出:11
解释:排列后甜点为 [1, 3, -9, 2, 4, 1, 3, -9, 2, 4, 1, 3, -9, 2, 4]
选择 [2, 4, 1, 3, -9, 2, 4, 1, 3] 这段连续甜点,最大总喜爱值为 11

解题思路:

  • 甜点序列是周期性的,每个周期包含 N 个甜点。
  • 需要考虑跨越多个周期的情况。
public static int solution(int N, int M, int[] data) {
        // Edit your code here
        int max_current = data[0];
        int max_global = data[0];
        int []d2=new int[N*M];
        for(int i=0;i<N*M;i++){
            d2[i]=data[i%N];
        }
        for (int i = 1; i <d2.length; i++) {
            max_current = Math.max(d2[i], max_current + d2[i]);
            if (max_current > max_global) {
                max_global = max_current;
            }
        }
        int total_sum = 0;
        for (int sweet : data) {
            total_sum += sweet;
        }
        int result;
        if (total_sum > 0) {
            result = Math.max(max_global, total_sum * M);
        } else {
            result = max_global;
        }
        return result;
    }

总结

一开始想的是这会不会是滑动窗口问题,但它会跨越多个周期,因此不是简单的滑动窗口问题。综合来看是最大子数组和问题。具体来说,它结合了以下几种算法和技术:

  1. Kadane's Algorithm:用于计算单个周期内的最大子数组和。
  2. 前缀和与后缀和:用于处理跨越多个周期的情况。
  3. 周期性数组处理:处理多个相同周期的数组拼接问题

上网查阅资料,得出多周期的最大子数组和可以像这样解题:

1.如果 M 为 1,直接返回单个周期的最大子数组和。

2.如果 M 大于 1,需要考虑跨越多个周期的情况。具体来说,可以将问题分解为以下几个部分:

(1)单个周期内的最大子数组和。

(2)跨越多个周期的最大子数组和,可以通过计算前缀和和后缀和来实现。