2170:使数组变成交替数组的最少操作数
2170. 使数组变成交替数组的最少操作数
题目描述
给你一个下标从 0 开始的数组 nums ,该数组由 n 个正整数组成。如果满足下述条件,则数组 nums 是一个 交替数组 :
- nums[i - 2] == nums[i] ,其中 2 <= i <= n - 1 。
- nums[i - 1] != nums[i] ,其中 1 <= i <= n - 1 。
在一步 操作 中,你可以选择下标 i 并将 nums[i] 更改 为 任一 正整数。返回使数组变成交替数组的 最少操作数 。
示例 1:
输入:nums = [3,1,3,2,4,3]
输出:3
解释:
使数组变成交替数组的方法之一是将该数组转换为 [3,1,3,1,3,1] 。
在这种情况下,操作数为 3 。
可以证明,操作数少于 3 的情况下,无法使数组变成交替数组。
示例 2:
输入:nums = [1,2,2,2,2]
输出:2
解释:
使数组变成交替数组的方法之一是将该数组转换为 [1,2,1,2,1].
在这种情况下,操作数为 2 。
注意,数组不能转换成 [2,2,2,2,2] 。因为在这种情况下,nums[0] == nums[1],不满足交替数组的条件。
提示:
- 1 <= nums.length <= 105
- 1 <= nums[i] <= 105
2、题目分析
根据交替数组的定义,可以抽取如下条件,即:
- 所有奇数下标的元素均相同;
- 所有偶数下标的元素均相同;
- 奇数下标的元素和偶数下标的元素不能相同。
3、解题思路
3.1、分别统计奇数和偶数位出现数组的数量,同时记录出现最多的数字和次多的数字
- int[] jiArr:奇数位各个数字出现的次数
- int jiMax:奇数位出现最多的数组
- int jiMaxNext:奇数位出现次多的数字
- int[] ouArr:偶数位各个数字出现的次数
- int ouMax:偶数位出现最多的数字
- int ouMaxNext:偶数位出现次多的数组。
3.2、贪心策略:
需要是的替换数字次数最小,我们需要以出现次数最多的数组为基准,替换跟基准不一样的数组。则最小次数为:n(总数字) - arr[ouMax] - arr[ouMaxNext]。
当奇数位众数和偶数位众数相等时,如果按照(上述策略)替换,则奇数位和偶数位数字相等,因此不满足条件。所以需要做特殊处理。即:当ouMax == jiMax,n - max( arr[ouMax] + arr[jiMaxNext], arr[ouMaxNext] + arr[jiMax])
4、代码实现
public int minimumOperations(int[] nums) {
// 题目可以转化为,所有奇数下表的元素都相等;所有偶数下标的元素不相等;但是奇数和偶数位置的元素不相等
// 分奇数和偶数讨论。
// nums[i] <= 100000;因此可以开辟连个大小为100000的数组来记录出现的众数
int maxNum = 100010;
int length = nums.length;
int[] jiArr = new int[maxNum];
int[] ouArr = new int[maxNum];
// 奇数位出现最多的元素
int jiMax = 0;
// 奇数位出现次多的元素
int jiMaxNext = 0;
// 偶数位出现最多的元素
int ouMax = 0;
// 偶数位出现次多的元素
int ouMaxNext = 0;
for (int i = 0; i < length; i++) {
int num = nums[i];
if (i % 2 == 0) {
ouArr[num]++;
if (ouMax == 0 || ouArr[num] > ouArr[ouMax]) {
ouMaxNext = ouMax;
ouMax = num;
// 跟第二大比较,不能等于第一大
} else if (num != ouMax && (ouMaxNext == 0 || ouArr[num] > ouArr[ouMaxNext])) {
ouMaxNext = num;
}
} else {
jiArr[num]++;
if (jiMax == 0 || jiArr[num] > jiArr[jiMax]) {
jiMaxNext = jiMax;
jiMax = num;
// 跟第二大比较,不能等于第一大
} else if (jiMax != num && (jiMaxNext == 0 || jiArr[num] > jiArr[jiMaxNext])) {
jiMaxNext = num;
}
}
}
if (ouMax != jiMax) {
return length - ouArr[ouMax] - jiArr[jiMax];
} else {
int max = Math.max(ouArr[ouMax] + jiArr[jiMaxNext], jiArr[jiMax] + ouArr[ouMaxNext]);
return length - max;
}
}