Problem: 3637. 三段式数组 I
文章目录
- [1. 整体思路](#1. 整体思路)
- [2. 完整代码](#2. 完整代码)
- [3. 时空复杂度](#3. 时空复杂度)
-
-
- [时间复杂度: O ( N ) O(N) O(N)](#时间复杂度: O ( N ) O(N) O(N))
- [空间复杂度: O ( 1 ) O(1) O(1)](#空间复杂度: O ( 1 ) O(1) O(1))
-
1. 整体思路
核心问题
我们需要验证数组是否为 升 -> 降 -> 升 的形状。
这个形状特征可以转化为单调性的变化次数:
- 开始 :必须是上升的 (
up)。 - 转折点 1 (峰) :从
升变为降。 - 转折点 2 (谷) :从
降变为升。 - 结束:必须保持上升状态直到结束,不能再有转折点。
这意味着,整个数组应该恰好包含 2 个转折点 ,或者说包含 3 个单调区间 (升、降、升)。
算法逻辑
- 初始检查 :
nums[0] >= nums[1]。如果开头不是上升的,直接返回false。 - 计数器
cnt:初始化为 1,代表这是第 1 个单调区间(初始的上升段)。 - 遍历 :从
i = 2开始遍历到末尾。- 平坡检查 :如果
nums[i-1] == nums[i],说明有平坡,不符合严格单调性,返回false。 - 转折点检测 :
nums[i-2] < nums[i-1]:前一步是上升。nums[i-1] < nums[i]:当前步是上升。- 如果这两个状态不一致(例如前一步升,当前步降;或前一步降,当前步升),说明发生了转折。
- 发生转折时,区间计数
cnt++。
- 平坡检查 :如果
- 最终检查 :如果
cnt == 3,说明恰好经历了"升 -> 降 -> 升"三个阶段,且没有多余的转折,返回true。
2. 完整代码
java
class Solution {
public boolean isTrionic(int[] nums) {
// 边界条件:数组长度过短无法形成三段
if (nums.length < 4) {
return false;
}
// 1. 检查起始段
// 必须以严格递增开始
if (nums[0] >= nums[1]) {
return false;
}
// cnt 记录单调区间的数量
// 初始为 1,因为我们已经确认了开头是上升区间
int cnt = 1;
// 2. 遍历数组,检测转折点
for (int i = 2; i < nums.length; i++) {
// 严格单调性检查:不允许相等元素(平坡)
if (nums[i - 1] == nums[i]) {
return false;
}
// 核心逻辑:检测单调性是否改变
// condition1: nums[i-2] < nums[i-1] (前一步是上升吗?)
// condition2: nums[i-1] < nums[i] (当前步是上升吗?)
// 如果两个条件真假不同 (即 !=),说明单调性发生了反转 (峰或谷)
if ((nums[i - 2] < nums[i - 1]) != (nums[i - 1] < nums[i])) {
cnt++;
}
}
// 3. 最终校验
// cnt == 3 意味着经历了: 上升(1) -> 峰转折 -> 下降(2) -> 谷转折 -> 上升(3)
// 且最后没有再转折,保持上升直到结束
return cnt == 3;
}
}
3. 时空复杂度
假设数组 nums 的长度为 N N N。
时间复杂度: O ( N ) O(N) O(N)
- 计算依据 :
- 代码包含一次
for循环,从 2 遍历到 N N N。 - 循环内部只包含常数次比较和自增操作。
- 代码包含一次
- 结论 : O ( N ) O(N) O(N)。
空间复杂度: O ( 1 ) O(1) O(1)
- 计算依据 :
- 只使用了常数个整型变量 (
cnt,i)。
- 只使用了常数个整型变量 (
- 结论 : O ( 1 ) O(1) O(1)。
参考灵神