📅  最后修改于: 2023-12-03 14:55:18.747000             🧑  作者: Mango
在圆形阵列中,我们将一组数首尾相接地排列成一个圆环,通过连续移动元素从而使得相邻元素的差异的总和最大。
例如,给定圆形阵列 [4, 2, 1, 5, 6]
,我们可以按照如下方式移动元素:
[2, 1, 5, 6, 4]
,总差异为 3 + 4 + 1 + 2 = 10
[1, 5, 6, 4, 2]
,总差异为 3 + 1 + 2 + 3 = 9
[6, 4, 2, 1, 5]
,总差异为 2 + 5 + 3 + 5 = 15
[5, 6, 4, 2, 1]
,总差异为 1 + 2 + 3 + 4 = 10
可以看到,右移 1 个位置时获得了最大的总差异。因此,最大化圆形阵列中连续差异的总和的问题,就是要在所有可能的移动中找到最大的总差异。
一个直接的想法是枚举所有可能的移动,将每个移动的差异总和都计算一遍,然后找到最大的总和。这个方法的时间复杂度是 $O(n^2)$,因为每个移动需要的计算都是 $O(n)$ 的。
更高效的方法是将圆形阵列想象成两份线性数组,然后在其中一份中枚举第一个位置,另一份中枚举最后一个位置,计算连续差异的总和,而不需要进行具体的移动操作。例如,将上述 [4, 2, 1, 5, 6]
转化为线性数组 [4, 2, 1, 5, 6, 4, 2, 1, 5, 6]
,分为两份 [4, 2, 1, 5, 6]
和 [4, 2, 1, 5, 6]
,则对于第一个位置为 $i$,最后一个位置为 $j$ 的情况,连续差异的总和可以计算为:
$$\sum_{k=i}^{j-1} \left| A[k] - A[k+1] \right|$$
其中,$A$ 为原始的线性数组,$|a|$ 表示 $a$ 的绝对值。
这个计算可以使用前缀和数组进行加速,令 $S[k] = \sum_{i=0}^{k-1} |A[i] - A[i+1]|$,则连续差异的总和为 $S[j-1] - S[i-1]$(需要注意边界条件)。这个方法的时间复杂度是 $O(n)$,空间复杂度也是 $O(n)$,因为需要保存前缀和数组。
下面是用 Python 实现的代码(假设输入的圆形阵列为列表 nums
,输出的最大差异总和为整数 ans
):
n = len(nums)
A = nums + nums
S = [0] * (2 * n - 1)
for i in range(1, 2 * n - 1):
S[i] = S[i-1] + abs(A[i] - A[i-1])
ans = 0
for i in range(n):
j = i + n
if j > 2 * n - 1:
break
sum_diff = S[j-1] - S[i]
ans = max(ans, sum_diff)
注意代码中的 A
和 S
数组的大小为 $2n-1$,因为需要将圆形阵列转化为线性数组,并在首尾各增加一个元素,以便避免边界的特判。