📌  相关文章
📜  圆形数组中的最大和,使得没有两个元素相邻 | 2套(1)

📅  最后修改于: 2023-12-03 15:37:17.169000             🧑  作者: Mango

圆形数组中的最大和,使得没有两个元素相邻

介绍

给定一个圆形数组,找出不相邻元素之和的最大值。

举个例子,对于数组 [3, 2, 5, 10, 7],我们无法同时选中第一个和第四个元素,因为它们是相邻的。这样,最大的可选和是 3 + 5 + 7 = 15

本题的主要难点在于数组是圆形的,因此不能只考虑相邻元素,还要考虑首尾元素是否相邻。

思路

我们可以考虑两种情况:选第一个元素和不选第一个元素。

首先,如果我们选中第一个元素,那么我们就不能选第二个和最后一个元素。因此,可选的数组是 [3, 5, 7],对应的可选和是 3 + 5 + 7 = 15

接着,如果我们不选第一个元素,那么我们就可以选取第二个和最后一个元素。对应的可选数组是 [2, 10],对应的可选和是 2 + 10 = 12

综上所述,我们只需要比较这两种情况的可选和,即可得到最大的不相邻元素和。

但是,这只是一个暴力的思路。考虑到本题具有重叠子问题的性质,我们可以使用动态规划来解决。

具体地,我们可以定义一个一维数组 dp[i],表示前 i 个元素选或不选的最大可选和。如果我们选取第 i 个元素,那么最大可选和为 dp[i-2] + nums[i](因为不能选相邻元素),否则为 dp[i-1]

注意,这里的数组是圆形的,因此需要对前两个元素进行特殊处理,具体地,如果选第一个元素,则不能选最后一个元素,可选数组是 [nums[0], nums[2], ..., nums[n-2]],对应的可选和是 dp[n-3] + nums[0]。如果不选第一个元素,则可选数组是 [nums[1], nums[2], ..., nums[n-1]],对应的可选和是 dp[n-2]

最终,我们需要比较 dp[n-3] + nums[0]dp[n-2],取其中较大的一个作为最终的可选和。

代码
def max_sum(nums: List[int]) -> int:
    n = len(nums)
    if n == 1:
        return nums[0]

    dp = [0] * n
    dp[0] = nums[0]
    dp[1] = max(nums[0], nums[1])

    for i in range(2, n - 1):
        dp[i] = max(dp[i-2] + nums[i], dp[i-1])

    temp1 = dp[n-3] + nums[0]
    dp[0], dp[1] = 0, nums[1]
    for i in range(2, n):
        dp[i] = max(dp[i-2] + nums[i], dp[i-1])
    temp2 = dp[n-1]

    return max(temp1, temp2)

上述代码中,我们使用了一个一维数组 dp 来记录前 i 个元素选或不选时的最大可选和。为了避免数组越界,我们特殊处理了前两个元素。最终,我们比较了选第一个元素和不选第一个元素两种情况的可选和,取其中较大的一个作为最终的返回结果。

总结

本题是一道相对简单的动态规划问题,重点在于如何定义状态和状态转移方程。需要特别注意的是,本题中的数组是圆形的,因此需要进行特殊处理。