问题描述
小S拿到了一个长度为 nn 的环形数组,并定义了两个下标 ii 和 jj 的贡献值公式为:
f(i, j) = (a_i + a_j) × dist(i, j)
其中 dist(i, j) 是下标 ii 和 jj 在数组中的最短距离。小S希望找到一对下标,使得它们的贡献值尽可能大。环形数组的特点是最左和最右的元素也是相邻的。你需要帮助她找到最大贡献值。
例如,给定数组 [1, 2, 3],由于是环形数组,任意两个下标的距离都是1,因此 f(2,3)=(2+3)×1=5f(2,3)=(2+3)×1=5。
测试样例
样例1:
输入:
n = 3,a = [1, 2, 3]
输出:5
样例2:
输入:
n = 4,a = [4, 1, 2, 3]
输出:12
样例3:
输入:
n = 5,a = [1, 5, 3, 7, 2]
输出:24好的,让我们来逐步解决这个问题。首先,我们需要理解环形数组的特性,即数组的首尾是相连的。因此,计算两个下标之间的最短距离时,需要考虑两种情况:
- 直接计算两个下标之间的距离。
- 计算从数组末尾绕回到数组开头的情况。
接下来,我们需要遍历所有可能的下标对 (i, j),并计算它们的贡献值 f(i, j)。为了找到最大贡献值,我们可以使用两层循环来遍历所有可能的下标对。
以下是一些代码提示,帮助你实现这个算法:
java
public class Main {
public static int
solution(int n,
int[] a) {
int
maxContributio
n = 0;
// 遍历所有可能
的下标对 (i, j)
for (int i =
0; i < n; i
++) {
for (int
j = 0; j
< n; j++)
{
if (i
!= j)
{
//
计
算
下
标
i
和
j
之
间
的
最
短
距
离
in
t
di
st
=
Ma
th
.
mi
n
(M
at
h.
ab
s
(i
-
j)
,
n
-
Ma
th
.
ab
s
(i
-
j)
);
//
计
算
贡
献
值
f
(i
,
j)
in
t
co
nt
ri
bu
ti
on
=
(a
[i
]
+
a
[j
])
*
di
st
;
//
更
新
最
大
贡
献
值
ma
xC
on
tr
ib
ut
io
n
=
Ma
th
.
ma
x
(m
ax
Co
nt
ri
bu
ti
on
,
co
nt
ri
bu
ti
on
);
}
}
}
return
maxContributio
n;
}
public static
void main(String
[] args) {
System.out.
println
(solution(3,
new int[]{1,
2, 3}) == 5);
System.out.
println
(solution(4,
new int[]{4,
1, 2, 3}) ==
12);
System.out.
println
(solution(5,
new int[]{1,
5, 3, 7, 2})
== 24);
}
}
代码解释:
- 遍历所有可能的下标对:我们使用两层循环来遍历所有可能的下标对
(i, j)。 - 计算最短距离:我们使用
Math.min(Math.abs(i - j), n - Math.abs(i - j))来计算下标i和j之间的最短距离。 - 计算贡献值:我们使用公式
(a[i] + a[j]) * dist来计算贡献值。 - 更新最大贡献值:我们使用
Math.max来更新最大贡献值。
代码解析
java
public class Main {
public static int
solution(int n,
int[] a) {
int
maxContributio
n = 0;
// 遍历所有可能
的下标对 (i, j)
for (int i =
0; i < n; i
++) {
for (int
j = 0; j
< n; j++)
{
if (i
!= j)
{
//
计
算
下
标
i
和
j
之
间
的
最
短
距
离
in
t
di
st
=
Ma
th
.
mi
n
(M
at
h.
ab
s
(i
-
j)
,
n
-
Ma
th
.
ab
s
(i
-
j)
);
//
计
算
贡
献
值
f
(i
,
j)
in
t
co
nt
ri
bu
ti
on
=
(a
[i
]
+
a
[j
])
*
di
st
;
//
更
新
最
大
贡
献
值
ma
xC
on
tr
ib
ut
io
n
=
Ma
th
.
ma
x
(m
ax
Co
nt
ri
bu
ti
on
,
co
nt
ri
bu
ti
on
);
}
}
}
return
maxContributio
n;
}
public static
void main(String
[] args) {
System.out.
println
(solution(3,
new int[]{1,
2, 3}) == 5);
System.out.
println
(solution(4,
new int[]{4,
1, 2, 3}) ==
12);
System.out.
println
(solution(5,
new int[]{1,
5, 3, 7, 2})
== 24);
}
}
代码结构
-
类定义:
public class Main:定义了一个公共类Main。
-
方法定义:
public static int solution(int n, int[] a):这是一个静态方法,接受两个参数:n表示数组的长度,a表示数组本身。该方法返回最大贡献值。
-
变量定义:
int maxContribution = 0;:初始化最大贡献值为 0。
-
双层循环:
for (int i = 0; i < n; i++):外层循环遍历数组中的每一个元素,i表示当前元素的下标。for (int j = 0; j < n; j++):内层循环遍历数组中的每一个元素,j表示当前元素的下标。if (i != j):确保i和j不是同一个下标。
-
计算最短距离:
int dist = Math.min(Math.abs(i - j), n - Math.abs(i - j));:计算下标i和j之间的最短距离。这里考虑了环形数组的特性,即数组的首尾相连。
-
计算贡献值:
int contribution = (a[i] + a[j]) * dist;:根据题目给出的公式f(i, j) = (a_i + a_j) × dist(i, j)计算贡献值。
-
更新最大贡献值:
maxContribution = Math.max(maxContribution, contribution);:使用Math.max函数更新最大贡献值。
-
返回结果:
return maxContribution;:返回计算得到的最大贡献值。
-
主方法:
public static void main(String[] args):主方法用于测试solution方法。它调用solution方法并打印结果,验证是否与预期结果一致。
代码逻辑
- 遍历所有可能的下标对:通过两层循环,遍历数组中的所有可能的下标对
(i, j)。 - 计算最短距离:根据环形数组的特性,计算下标
i和j之间的最短距离。 - 计算贡献值:根据题目给出的公式,计算每个下标对的贡献值。
- 更新最大贡献值:在每次计算贡献值后,更新最大贡献值。
- 返回最大贡献值:最终返回计算得到的最大贡献值。