看到题的前十五分钟,发呆。看似简单,其实不会。暴力可解,但是可能会超时。
题目不搬运了。
既然暴力可解,那顺着暴力的思路,把一些值存下来,是不是就不用重复计算,不超时了。有点像动态规划。
输入数组是maxHeights
(原题是list, 这里为了好看假设是数组,真正实现的时候用list实现就行)
使用两个数组来辅助
fa
:fa[i]
存储第i
个值作为塔尖的时候,左侧序列(包括第i
个值)的和
fb
:fb[i]
存储第i
个值作为塔尖的时候,右侧序列(包括第i
个值)的和
则根据题意,有以下关系
对于fa
f
a
[
i
]
=
{
m
a
x
H
e
i
g
h
t
s
[
0
]
,
i
=
0
f
a
[
i
−
1
]
+
m
a
x
H
e
i
g
h
t
s
[
i
]
,
i
>
0
,
m
a
x
H
e
i
g
h
t
s
[
i
]
≥
m
a
x
H
e
i
g
h
t
s
[
i
−
1
]
f
a
[
j
]
+
m
a
x
H
e
i
g
h
t
s
[
i
]
∗
(
i
−
j
)
,
i
>
0
,
m
a
x
H
e
i
g
h
t
s
[
i
]
<
m
a
x
H
e
i
g
h
t
s
[
i
−
1
]
fa[i]=\begin{cases} maxHeights[0],\quad i=0 \\\\ fa[i - 1] + maxHeights[i],\quad i\gt0,maxHeights[i]\geq maxHeights[i-1] \\\\ fa[j] + maxHeights[i] * (i - j),\quad i\gt0,maxHeights[i]\lt maxHeights[i-1] \end{cases}
fa[i]=⎩
⎨
⎧maxHeights[0],i=0fa[i−1]+maxHeights[i],i>0,maxHeights[i]≥maxHeights[i−1]fa[j]+maxHeights[i]∗(i−j),i>0,maxHeights[i]<maxHeights[i−1]
其中 j
是从i-1
到0
,第一个小于等于maxHeight[i]
的值的下标
优化下,可以写成
f
a
[
i
]
=
{
m
a
x
H
e
i
g
h
t
s
[
0
]
,
i
=
0
f
a
[
j
]
+
m
a
x
H
e
i
g
h
t
s
[
i
]
∗
(
i
−
j
)
,
i
>
0
fa[i]=\begin{cases} maxHeights[0],\quad i=0 \\\\ fa[j] + maxHeights[i] * (i - j),\quad i\gt0 \end{cases}
fa[i]=⎩
⎨
⎧maxHeights[0],i=0fa[j]+maxHeights[i]∗(i−j),i>0
同理,fb
f
b
[
i
]
=
{
m
a
x
H
e
i
g
h
t
s
[
i
]
,
i
=
l
e
n
−
1
f
b
[
i
+
1
]
+
m
a
x
H
e
i
g
h
t
s
[
i
]
,
i
<
l
e
n
−
1
,
m
a
x
H
e
i
g
h
t
s
[
i
]
≥
m
a
x
H
e
i
g
h
t
s
[
i
+
1
]
f
b
[
j
]
+
m
a
x
H
e
i
g
h
t
s
[
i
]
∗
(
j
−
i
)
,
i
<
l
e
n
−
1
,
m
a
x
H
e
i
g
h
t
s
[
i
]
<
m
a
x
H
e
i
g
h
t
s
[
i
+
1
]
fb[i]=\begin{cases} maxHeights[i],\quad i=len - 1 \\\\ fb[i + 1] + maxHeights[i],\quad i\lt len - 1,maxHeights[i]\geq maxHeights[i+1] \\\\ fb[j] + maxHeights[i] * (j - i),\quad i\lt len - 1,maxHeights[i]\lt maxHeights[i+1] \end{cases}
fb[i]=⎩
⎨
⎧maxHeights[i],i=len−1fb[i+1]+maxHeights[i],i<len−1,maxHeights[i]≥maxHeights[i+1]fb[j]+maxHeights[i]∗(j−i),i<len−1,maxHeights[i]<maxHeights[i+1]
优化下,可以写成
f
b
[
i
]
=
{
m
a
x
H
e
i
g
h
t
s
[
i
]
,
i
=
l
e
n
−
1
f
b
[
j
]
+
m
a
x
H
e
i
g
h
t
s
[
i
]
∗
(
j
−
i
)
,
i
<
l
e
n
−
1
fb[i]=\begin{cases} maxHeights[i],\quad i=len - 1 \\\\ fb[j] + maxHeights[i] * (j - i),\quad i\lt len - 1 \end{cases}
fb[i]=⎩
⎨
⎧maxHeights[i],i=len−1fb[j]+maxHeights[i]∗(j−i),i<len−1
其中 j
是从i+1
到len-1
,第一个小于等于maxHeight[i]
的值的下标
len
是数组的长度。
则代码如下
public long maximumSumOfHeights(List<Integer> maxHeights) {
int len = maxHeights.size();
// 对应fa
long[] leftsum = new long[len];
// 对应fb
long[] rightsum = new long[len];
leftsum[0] = maxHeights.get(0);
rightsum[len - 1] = maxHeights.get(len - 1);
int j;
for (int i = 1; i < len; ++i) {
// 算leftsum
j = i - 1;
while (j >= 0 && maxHeights.get(j) > maxHeights.get(i)) {
--j;
}
// 必须加long,否则超出范围
leftsum[i] = (j >= 0 ? leftsum[j] : 0) + (i - j) * (long)maxHeights.get(i);
// 算rightsum
j = len - i;
while(j < len && maxHeights.get(j) > maxHeights.get(len - 1 - i)) {
++j;
}
// 必须加long,否则超出范围
rightsum[len - 1 - i] = (j < len ? rightsum[j] : 0) + (j - (len - 1 - i)) * (long)maxHeights.get(len - 1 - i);
}
long res = 0;
for (int i = 0; i < len; ++i) {
res = res > (leftsum[i] - maxHeights.get(i) + rightsum[i]) ? res : (leftsum[i] - maxHeights.get(i) + rightsum[i]);
}
return res;
}
看了下官方的题解,有个单调栈的,有空学下。TODO