📅  最后修改于: 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
个元素选或不选时的最大可选和。为了避免数组越界,我们特殊处理了前两个元素。最终,我们比较了选第一个元素和不选第一个元素两种情况的可选和,取其中较大的一个作为最终的返回结果。
本题是一道相对简单的动态规划问题,重点在于如何定义状态和状态转移方程。需要特别注意的是,本题中的数组是圆形的,因此需要进行特殊处理。