【算法题解析】数组中的美丽值统计(美丽值之和)
✨题目描述
给定一个下标从 0
开始的整数数组 nums
。对每个下标 i
(满足 1 <= i <= nums.length - 2
),我们定义一个整数的 美丽值(beauty),具体规则如下:
- 美丽值为 2:如果存在
j < i < k
,满足nums[j] < nums[i] < nums[k]
; - 美丽值为 1:如果不满足上面的条件,但满足
nums[i-1] < nums[i] < nums[i+1]
; - 美丽值为 0:如果以上条件都不满足。
请你返回所有 1 <= i <= nums.length - 2
范围内的 nums[i]
的 美丽值总和。
✅ 示例 1:
输入:nums = [1, 2, 3]
输出:2
解释:
对于 i = 1:
nums[0] < nums[1] < nums[2] => 1 < 2 < 3,满足美丽值为 2。
总和为 2。
✅ 示例 2:
输入:nums = [2, 4, 6, 4]
输出:1
解释:
对于 i = 1:nums[0] = 2 < 4 < 6 = nums[2],美丽值 = 2;
对于 i = 2:nums[1] = 4 < 6 > 4 = nums[3],不满足美丽值2,也不满足美丽值1;
因此总和为 2 + 0 = 2。
但实际上 leftMax[1] = 4,nums[2] = 6,不满足 leftMax < nums[2],所以美丽值为 1(满足 nums[1] < nums[2] > nums[3]),总和为 1。
✅ 示例 3:
输入:nums = [3, 2, 1]
输出:0
解释:
对于 i = 1:nums[0] = 3 > 2 > 1 = nums[2],不满足任何条件。
🧠 解题思路分析
核心目标
我们需要针对每一个中间元素 nums[i] (1 <= i <= n-2)
,判断它是否满足:
- 有一个左边的元素小于它,且右边有一个元素大于它(美丽值 = 2)
- 或者左右相邻元素满足 nums[i-1] < nums[i] < nums[i+1](美丽值 = 1)
- 否则(美丽值 = 0)
为了高效完成这个判断,我们可以预处理:
- 每个位置左边的最大值
leftMax[i]
- 每个位置右边的最小值
rightMin[i]
为什么这样处理?
我们并不需要枚举所有的 j < i
和 k > i
,只需要知道:
nums[i]
是否大于它左边的所有值(即大于leftMax[i-1]
)nums[i]
是否小于它右边的所有值(即小于rightMin[i+1]
)
如果这两个条件都满足,那么一定存在某个 j
和 k
使得 nums[j] < nums[i] < nums[k]
成立,从而美丽值为 2。
🛠 解题方法(Python 实现)
from typing import List
class Solution:
def sumOfBeauties(self, nums: List[int]) -> int:
n = len(nums)
leftMax = [0] * n
rightMin = [0] * n
# 构造左侧最大值数组
leftMax[0] = nums[0]
for i in range(1, n):
leftMax[i] = max(leftMax[i - 1], nums[i])
# 构造右侧最小值数组
rightMin[-1] = nums[-1]
for i in range(n - 2, -1, -1):
rightMin[i] = min(rightMin[i + 1], nums[i])
total_beauty = 0
for i in range(1, n - 1):
if leftMax[i - 1] < nums[i] < rightMin[i + 1]:
total_beauty += 2
elif nums[i - 1] < nums[i] < nums[i + 1]:
total_beauty += 1
# 否则为0,省略不加
return total_beauty
⏱ 时间复杂度与空间复杂度
操作 | 复杂度 |
---|---|
时间复杂度 | O(n) 三次线性扫描:一次构造 leftMax ,一次构造 rightMin ,一次遍历判断 |
空间复杂度 | O(n) 需要两个额外数组存储最大/最小值 |
该解法已经是线性时间和线性空间的最优解,适用于数组长度在 10^5
级别的情况。
🔍 方法分析与对比
方法 | 优点 | 缺点 |
---|---|---|
枚举 j 和 k(暴力法) | 容易理解 | 时间复杂度 O(n²),不可接受 |
前后缀数组法(本解法) | 时间复杂度 O(n),适配大数据 | 需要额外 O(n) 空间 |
✅ 总结
这道题考察了对区间最值的预处理技巧:
- 类似于“前缀最大值”“后缀最小值”这种技巧在很多问题中都非常常用,比如“下一个更大元素”、“最大子数组”等。
- 本题的本质是利用这些前缀/后缀信息,避免了不必要的暴力枚举,达到了线性优化效果。