环形数组中的最大贡献值
让我们先来阅读一下题目:
小S拿到了一个长度为 nn 的环形数组,并定义了两个下标 i 和 j 的贡献值公式为:
f(i, j) = (a_i + a_j) × dist(i, j)
其中 dist(i, j) 是下标 i 和 j 在数组中的最短距离。小S希望找到一对下标,使得它们的贡献值尽可能大。环形数组的特点是最左和最右的元素也是相邻的。你需要帮助她找到最大贡献值。
例如,给定数组 [1, 2, 3],由于是环形数组,任意两个下标的距离都是1,因此 f(2,3)=(2+3)×1=5f(2,3)=(2+3)×1=5。
观察输入:包括两个值,一个整型,为数组长度,另一个为数组名
观察输出:为最大贡献值
我们先看一下样例:由于 [1, 2, 3]是环形数组,那么三者之间两两的最短都为1,选择最大的两个数:2与3,求得结构(2+3)*(2-1)得5.
样例理解成功,开始写题
一般看到环形数组,我们都会想到将数组连接起来
让第一个元素和最后一个元素相邻
newlis=a+a
然后进行遍历
for i in range(2*n-1):
for j in range(i+1,2*n):
ans=max((k[i]+k[j])*(j-i%n),ans)
但是这种惯性思维写出来之后提交,会发现:答案错误
为什么呢???
贡献值由两个元素的值和它们之间的最小距离共同决定
影响因素有a.两个元素的值,b.它们之间的最小距离
分析可知,问题出在“元素之间的最小距离”的计算上!
现在这样获得的是最大距离!!
->我们重新思考,如何获得最小距离:
->min(j-i,n-j+i)
举个例子:
对于第一个数和最后一个数,它们之间的距离可以用1,也可以用n-1来表示
其中,1==n-j+i,n-1=j-i
因此,代码可写为:
k=a+a
ans=0
for i in range(2*n-1):
for j in range(i+1,2*n):
ans=max((k[i]+k[j])*(min(j-i,n-j+i)),ans)
print(ans)
return ans
**这其中最重要的就是贡献度的计算:ans=max((k[i]+k[j])*(min(j-i,n-j+i)),ans)**
特别是其中最短距离的计算
我们还可以思考进一步优化: 不需要k=a+a,直接使用a数组就可以
因为min(j-i,n-j+i)已经考虑的是环形的最小距离了
这种方法的时间复杂度是 O(n^2),比前述的k=a+a的速度快4倍。
这题在题库中虽然被归类为“中”难度,但是真正动手做起来,并没有觉得那么难,更重要的是冷静下来分析,找到解题的突破口——“最短距离”的计算。
环形数组的引入给问题增加了一定的难度,但只要我们抓住了首位相邻这个特点,并将其转化为数学公式,那么解题就变得相对容易了。
今日刷题打卡成功,希望明天可以坚持继续分享~