题目解析
这个问题的核心是计算数组中每个元素的 L(i) 和 R(i),然后通过这两个值计算 MAX(i),并找出最大值。为了帮助大家更好地理解和解决这个问题,我将从以下几个方面进行详细分析:
-
L(i) 和 R(i) 的定义与理解:
- L(i) 是满足条件
a[j] > a[i]且j < i中的最大j。如果不存在这样的j,则L(i) = 0。 - R(i) 是满足条件
a[k] > a[i]且k > i中的最小k。如果不存在这样的k,则R(i) = 0。
- L(i) 是满足条件
-
MAX(i) 的定义:
MAX(i) = L(i) * R(i),我们要求的是所有i值中的MAX(i)的最大值。
思路分析
根据题目要求,我们需要遍历数组来为每个位置计算 L(i) 和 R(i),然后计算每个 MAX(i)。这个问题的解决方案可以分成以下几个步骤:
-
计算 L(i) :
- 对于每个元素
a[i],我们需要从左到右检查其前面的所有元素,找到最大的j,使得a[j] > a[i]。这个过程是线性扫描。
- 对于每个元素
-
计算 R(i) :
- 对于每个元素
a[i],我们需要从右到左检查其后面的所有元素,找到最小的k,使得a[k] > a[i]。这个过程也是线性扫描。
- 对于每个元素
-
计算 MAX(i) :
- 对于每个位置
i,我们有了L(i)和R(i),可以直接计算出MAX(i)。
- 对于每个位置
-
找出最大值:
- 最后,遍历所有
i,找出MAX(i)的最大值。
- 最后,遍历所有
优化策略
直接遍历每个 i,计算 L(i) 和 R(i) 的时间复杂度是 O(n^2),这个时间复杂度对于较大的 n 来说会比较慢。为了优化这个过程,我们可以考虑使用栈来提高效率,具体方法是利用单调栈来加速 L(i) 和 R(i) 的计算。
代码实现
pythonCopy Code
def solution(n, array):
# 初始化 L 和 R 数组
L = [0] * n
R = [0] * n
# 计算 L(i)
stack = []
for i in range(n):
while stack and array[stack[-1]] <= array[i]:
stack.pop()
if stack:
L[i] = stack[-1] + 1 # 1-based index
stack.append(i)
# 计算 R(i)
stack = []
for i in range(n-1, -1, -1):
while stack and array[stack[-1]] <= array[i]:
stack.pop()
if stack:
R[i] = stack[-1] + 1 # 1-based index
stack.append(i)
# 计算 MAX(i) 并找出最大值
max_value = 0
for i in range(n):
max_value = max(max_value, L[i] * R[i])
return max_value
# 测试用例
print(solution(5, [5, 4, 3, 4, 5])) # 输出: 8
print(solution(6, [2, 1, 4, 3, 6, 5])) # 输出: 15
print(solution(7, [1, 2, 3, 4, 5, 6, 7])) # 输出: 0
代码详解
-
计算 L(i) :
- 我们使用一个栈来帮助寻找每个
i左侧的第一个比a[i]大的元素。栈内存储的是元素的索引,栈顶始终保持的是最近的比当前元素大的元素的索引。 - 如果栈顶的元素小于等于当前元素,我们就弹出栈顶,直到栈顶的元素大于当前元素。如果栈不为空,栈顶元素对应的就是我们需要的
L(i)。
- 我们使用一个栈来帮助寻找每个
-
计算 R(i) :
- 同样地,我们使用一个栈来帮助寻找每个
i右侧的第一个比a[i]大的元素,过程与计算L(i)类似,只不过我们是从右向左扫描。
- 同样地,我们使用一个栈来帮助寻找每个
-
计算
MAX(i):- 通过前两步的结果,我们可以直接计算出每个
i的MAX(i) = L(i) * R(i),然后找到最大的MAX(i)。
- 通过前两步的结果,我们可以直接计算出每个
测试结果
- 对于输入
array = [5, 4, 3, 4, 5],输出应为 8。 - 对于输入
array = [2, 1, 4, 3, 6, 5],输出应为 15。 - 对于输入
array = [1, 2, 3, 4, 5, 6, 7],输出应为 0。
总结
- 通过栈的方式优化了计算
L(i)和R(i)的过程,避免了暴力的双重循环。 - 时间复杂度降低到
O(n),适合处理大规模数据。 - 通过合理的数据结构和算法优化,提高了问题解决的效率。
学习计划与总结
- 刷题的策略:可以将问题划分成几个小部分,每部分逐步实现,逐步优化。先理解问题本质,再考虑时间复杂度,最后考虑如何优化。
- 学习栈与单调栈的应用:栈是非常重要的数据结构,可以帮助我们高效地解决一些搜索问题。单调栈的应用场景非常广泛,特别是当需要寻找某个元素左侧或右侧第一个满足条件的元素时。
希望通过这篇笔记,大家能够对栈的使用有更深入的理解,并能够在今后的算法学习中更好地应用这些知识点。