“Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情。”
一、题目描述
给你一个下标从 0 开始的整数数组 nums ,如果满足下述条件,则认为数组 nums 是一个 美丽数组 :
nums.length为偶数- 对所有满足
i % 2 == 0的下标i,nums[i] != nums[i + 1]均成立
注意,空数组同样认为是美丽数组。
你可以从 nums 中删除任意数量的元素。当你删除一个元素时,被删除元素右侧的所有元素将会向左移动一个单位以填补空缺,而左侧的元素将会保持 不变 。
返回使 nums 变为美丽数组所需删除的 最少 元素数目 。
示例 1:
输入: nums = [1,1,2,3,5]
输出: 1
解释: 可以删除 nums[0] 或 nums[1] ,这样得到的 nums = [1,2,3,5] 是一个美丽数组。可以证明,要想使 nums 变为美丽数组,至少需要删除 1 个元素。
示例 2:
输入: nums = [1,1,2,2,3,3]
输出: 2
解释: 可以删除 nums[0] 和 nums[5] ,这样得到的 nums = [1,2,2,3] 是一个美丽数组。可以证明,要想使 nums 变为美丽数组,至少需要删除 2 个元素。
提示:
1 <= nums.length <= 1050 <= nums[i] <= 105
二、思路分析
这道题要返回使 nums 变为美丽数组所需删除的 最少 元素数目 ,翻译一下也就是,在尽可能少地删除数组元素的前提下,①下标是偶数的元素不能等于其后一个元素;②删除后的数组长度要为偶数。
笔者一看到要删除数组元素,就想到了 JS 中的 splice 方法,并作为思考方向,但其实并不需要真的删除数组,我们要的只是删除数组元素的次数,定义一个变量维护就好了。
那么在不删除数组元素的前提下,怎么实现删除数组元素的效果呢?思路如下:
- 遍历
nums数组,第一个元素的下标肯定是偶数,因此判断其是否等于它的后一个元素,不是的话就遍历下一个下标为偶数的元素,是的话就将删除次数+1并继续遍历后一个元素(为什么是遍历后一个元素而不是遍历后后一个元素呢?因为这里相当于删除操作,删除了一个元素后,后面的元素就会顶上来,取代被删除元素的位置,此时就要继续判断当前元素是否等于后一个元素)。 - 遍历完成之后,还需判断删除后的数组的长度是否为偶数,不是的话说明不是美丽数组,要再删除一个元素(删除最后一个元素即可,直接将删除次数
+1);如果是偶数的话就可以返回结果了,此时删除后的数组已经是美丽数组了。
注意1:遍历的区间是
[0, nums.length - 1),因为要判断当前元素是否与其后一个元素相等,当遍历到nums.length - 1的位置时,就会发生数组越界。
注意2:为什么在遍历时不用判断当前元素的下标是否为偶数?因为数组是从
0开始遍历的,我们在遍历时保证当前元素的下标始终为偶数。
那么如何保证呢?一开始下标就为偶数,如果nums[i] === nums[i + 1],下标后移一位,但依然是偶数,相当于元素被删除后多余的空间被后面的元素取代;如果nums[i] !== nums[i + 1],下标自然就后移两位,此时依然为偶数。自始至终,下标始终为偶数,因此也就不需要判断当前元素的下标是否为偶数了。
三、AC 代码
/**
* @param {number[]} nums
* @return {number}
*/
var minDeletion = function(nums) {
let ans = 0;
let i = 0;
while (i < nums.length - 1) {
if (nums[i] === nums[i + 1]) {
ans++;
i++;
continue;
}
i += 2;
}
if ((nums.length - ans) % 2) {
ans++;
}
return ans;
};