2170:使数组变成交替数组的最少操作数

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;
        }
    }
  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值