Medium
题目描述
给你一个下标从 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] 是一个美丽数组。可以证明你需要至少 1 次删除操作才能使 nums 变为美丽数组。
示例 2:
输入:nums = [1,1,2,2,3,3]
输出:2
解释:你可以删除 nums[0] 和 nums[5] ,这样得到的 nums = [1,2,2,3] 是一个美丽数组。可以证明你需要至少 2 次删除操作才能使 nums 变为美丽数组。
提示:
1 <= nums.length <= 10^50 <= nums[i] <= 10^5
解题思路
这道题的核心在于理解美丽数组的定义:数组长度必须是偶数,且对于所有偶数下标位置,该位置的元素不能等于下一个位置的元素。
贪心思路:
- 我们可以贪心地构造美丽数组,从左到右遍历原数组
- 对于每一对相邻元素,如果它们相等,我们必须删除其中一个
- 关键观察:当遇到相邻相等元素时,删除后面那个元素更优,因为这样不会影响前面已经配对好的元素
- 最后如果剩余元素个数是奇数,还需要再删除一个元素使长度变为偶数
具体算法:
- 用一个指针模拟构造美丽数组的过程
- 遍历原数组,对于每个元素,判断是否能与前一个未配对的元素组成有效对
- 如果当前元素与前一个未配对元素相同,则删除当前元素(删除计数+1)
- 否则,将当前元素加入结果中
- 最终如果结果长度为奇数,需要额外删除一个元素
这种贪心策略是最优的,因为我们总是在必须删除时才删除,且选择删除不会影响已有配对的元素。
代码实现
class Solution {
public:
int minDeletion(vector<int>& nums) {
int deletions = 0;
int validCount = 0;
for (int i = 0; i < nums.size(); i++) {
// 如果当前位置是偶数位置且与下一个元素相等,删除下一个元素
if (validCount % 2 == 0 && i + 1 < nums.size() && nums[i] == nums[i + 1]) {
deletions++;
} else {
validCount++;
}
}
// 如果最终长度是奇数,需要再删除一个
if (validCount % 2 == 1) {
deletions++;
}
return deletions;
}
};
class Solution:
def minDeletion(self, nums: List[int]) -> int:
deletions = 0
valid_count = 0
i = 0
while i < len(nums):
# 如果当前是偶数位置且与下一个元素相等
if valid_count % 2 == 0 and i + 1 < len(nums) and nums[i] == nums[i + 1]:
deletions += 1
i += 1 # 跳过下一个元素
else:
valid_count += 1
i += 1
# 如果最终长度是奇数,需要再删除一个
if valid_count % 2 == 1:
deletions += 1
return deletions
public class Solution {
public int MinDeletion(int[] nums) {
int deletions = 0;
int validCount = 0;
for (int i = 0; i < nums.Length; i++) {
// 如果当前位置是偶数位置且与下一个元素相等,删除下一个元素
if (validCount % 2 == 0 && i + 1 < nums.Length && nums[i] == nums[i + 1]) {
deletions++;
} else {
validCount++;
}
}
// 如果最终长度是奇数,需要再删除一个
if (validCount % 2 == 1) {
deletions++;
}
return deletions;
}
}
var minDeletion = function(nums) {
let deletions = 0;
let i = 0;
while (i < nums.length - 1) {
if (nums[i] === nums[i + 1]) {
deletions++;
i++;
} else {
i += 2;
}
}
let remainingLength = nums.length - deletions;
if (remainingLength % 2 === 1) {
deletions++;
}
return deletions;
};
复杂度分析
| 复杂度类型 | 复杂度 |
|---|---|
| 时间复杂度 | O(n) |
| 空间复杂度 | O(1) |