1. 问题描述与理解
今天我们来解析一道来自米哈游2026年春招的算法题——"乱翘的数组hard"。题目要求我们将给定的数组转换为所谓的"乱翘数组",即满足以下两个条件:
- 相邻元素不相等
- 每个中间元素必须严格大于或小于其左右相邻元素
换句话说,我们需要找到一个最长的摆动子序列,其中相邻元素的大小关系交替变化(即"上升-下降-上升..."或"下降-上升-下降..."的模式)。最终,我们需要计算最少需要删除多少个元素才能将原数组转换为这样的摆动序列。
注意:这里的"删除"操作实际上是指跳过某些元素来构造子序列,而不是物理上从数组中移除元素。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 问题分析与解法思路
2.1 问题转化
这个问题可以转化为寻找数组中最长的摆动子序列的长度。因为:
最少删除数量 = 原数组长度 - 最长摆动子序列长度
摆动子序列的定义是:对于序列中的每个元素(除了第一个和最后一个),它要么同时大于前后相邻元素,要么同时小于前后相邻元素。
2.2 贪心算法思路
我们可以使用贪心算法在线性时间内解决这个问题。基本思路是:
- 遍历数组,记录当前趋势(上升或下降)
- 每当趋势发生变化时,摆动序列长度加1
- 忽略那些不影响趋势变化的中间元素
这种方法之所以有效,是因为我们只需要关注趋势变化的转折点,这些点自然构成了最长的摆动序列。
2.3 算法复杂度分析
- 时间复杂度:O(n),因为我们只需要一次遍历数组
- 空间复杂度:O(1),只需要几个变量来存储状态
3. 具体实现与代码解析
3.1 Java实现
java复制public int minDeletionsToWiggle(int[] nums) {
if (nums.length < 2) return 0;
int prevDiff = nums[1] - nums[0];
int count = prevDiff != 0 ? 2 : 1;
for (int i = 2; i < nums.length; i++) {
int currDiff = nums[i] - nums[i-1];
if ((prevDiff > 0 && curr
