最大化糖果美味值问题| 豆包MarsCode AI刷题

128 阅读5分钟

1.问题描述

小C面临一个选择问题:她可以从编号为1到n的糖果中任意选择一些糖果作为奖励,但需要遵守一个限制规则:如果选择了编号为i的糖果,那么编号为i-1、i-2、i+1、i+2的糖果将不能被选择。每个糖果都有一个对应的美味值,小C希望所选糖果的美味值之和最大。

例如:当有7个糖果,编号为1到7,美味值分别为 3, 1, 2, 7, 10, 2, 4,小C可以选择编号为1、4、7的糖果,这样可以得到最大美味值之和为 3 + 7 + 4 = 14

2.问题解决代码及注释(java)

解决问题的方法,计算在不相邻的元素中选择最大和的问题。 每个元素代表一个价值不相邻元素的最大和。

1.如果数组长度为0,没有元素可以取,返回0; 如果数组长度为1,只有一个元素可以取,返回该元素; 如果数组长度为2,取两个元素中的最大值。

public static int solution(int n, int[] a) {
         if(n == 0) return 0;
         if(n == 1) return a[0];
         if(n == 2) return Math.max(a[0], a[1]);         

2.创建一个动态规划数组dp,长度为n+1,初始化dp[0]为0; dp[1]为第一个元素,因为只有一个元素可以取;dp[2]为前两个元素中的最大值

        int[] dp = new int[n+1];
        dp[0] = 0;
        dp[1] = a[0];
        dp[2] = Math.max(a[0], a[1]);

3.从第3个元素开始遍历数组;dp[i]表示到第i个元素为止,不相邻元素的最大和;取当前元素加上i-3位置的dp值(因为不能相邻,所以是i-3),和前一个dp值(即不取当前元素)中的最大值

        for(int i = 3; i <= n; i++){
            dp[i] = Math.max(dp[i-1], a[i-1] + (i-3 >= 0 ? dp[i-3] : 0));
        }

4.返回最后两个dp值中的最大值,因为可能最后两个元素都不取

 return Math.max(dp[n-1], dp[n]);

3.程序UML类图

类图.png

4.程序数据结构分析

数组 a

  • 描述: 数组 a 是一个整数数组,用于存储每个元素的价值。
  • 用途: 作为输入参数传递给 solution 方法,表示问题的输入数据。
  • 示例: 在 main 方法中,数组 a 被初始化为 {3, 1, 2, 7, 10, 2, 4} 或其他测试用例。

数组 dp

  • 描述: 数组 dp 是一个动态规划数组,用于存储到每个位置为止不相邻元素的最大和。
  • 用途: 在 solution 方法中,通过动态规划的思想,逐步计算并更新 dp 数组的值,最终得到不相邻元素的最大和。
  • 初始化:
    • dp[0] = 0: 表示没有元素时,最大和为 0。
    • dp[1] = a[0]: 表示只有一个元素时,最大和为该元素的值。
    • dp[2] = Math.max(a[0], a[1]): 表示有两个元素时,最大和为这两个元素中的较大值。
  • 更新规则: 对于每个位置 i(从 3 开始),dp[i] 的值通过以下公式计算:
    dp[i] = Math.max(dp[i-1], a[i-1] + (i-3 >= 0 ? dp[i-3] : 0));
    
    • dp[i-1]: 表示不取当前元素时的最大和。
    • a[i-1] + (i-3 >= 0 ? dp[i-3] : 0): 表示取当前元素时的最大和,加上前一个不相邻元素的最大和(即 dp[i-3])。

数据结构分析总结

  • 数组 a: 用于存储输入数据,表示每个元素的价值。
  • 数组 dp: 用于动态规划计算,存储到每个位置为止不相邻元素的最大和。

通过这两个数组的配合使用,程序能够有效地解决在不相邻的元素中选择最大和的问题。

5.算法分析与思考

问题描述

该程序解决的问题是:给定一个整数数组 a,选择数组中的若干个不相邻元素,使得这些元素的和最大。

算法思路

该问题可以使用动态规划(Dynamic Programming, DP)来解决。动态规划是一种将复杂问题分解成更小的子问题来解决的技术。

动态规划步骤
  1. 定义状态

    • dp[i] 表示到第 i 个元素为止,不相邻元素的最大和。
  2. 状态转移方程

    • 对于每个位置 i(从 3 开始),有两种选择:
      • 不取当前元素 a[i-1],则最大和为 dp[i-1]
      • 取当前元素 a[i-1],则最大和为 a[i-1] + dp[i-3](因为不能相邻,所以是 i-3)。
    • 因此,状态转移方程为:
      dp[i] = Math.max(dp[i-1], a[i-1] + (i-3 >= 0 ? dp[i-3] : 0));
      
  3. 初始化

    • dp[0] = 0:没有元素时,最大和为 0。
    • dp[1] = a[0]:只有一个元素时,最大和为该元素的值。
    • dp[2] = Math.max(a[0], a[1]):有两个元素时,最大和为这两个元素中的较大值。
  4. 结果

    • 最终结果是 dp[n]dp[n-1] 中的最大值,因为可能最后两个元素都不取。
算法复杂度分析
  • 时间复杂度:O(n),其中 n 是数组 a 的长度。因为我们需要遍历一次数组来填充 dp 数组。
  • 空间复杂度:O(n),因为我们需要一个长度为 n+1dp 数组来存储中间结果。
总结

该程序使用动态规划算法解决了在不相邻的元素中选择最大和的问题。通过定义合适的状态和状态转移方程,并进行适当的初始化,我们能够高效地计算出结果。该算法的时间复杂度为 O(n),空间复杂度为 O(n),具有较好的性能。