2009. 使数组连续的最少操作数

2009. 使数组连续的最少操作数

问题描述

给你一个整数数组 nums 。每一次操作中,你可以将 nums任意 一个元素替换成 任意 整数。

如果 nums 满足以下条件,那么它是 连续的

  • nums 中所有元素都是 互不相同 的。
  • nums最大 元素与 最小 元素的差等于 nums.length - 1

比方说,nums = [4, 2, 5, 3]连续的 ,但是 nums = [1, 2, 3, 5, 6] 不是连续的

请你返回使 nums 连续最少 操作次数。

示例 1:

输入:nums = [4,2,5,3]
输出:0
解释:nums 已经是连续的了。

示例 2:

输入:nums = [1,2,3,5,6]
输出:1
解释:一个可能的解是将最后一个元素变为 4 。
结果数组为 [1,2,3,5,4] ,是连续数组。

示例 3:

输入:nums = [1,10,100,1000]
输出:3
解释:一个可能的解是:
- 将第二个元素变为 2 。
- 将第三个元素变为 3 。
- 将第四个元素变为 4 。
结果数组为 [1,2,3,4] ,是连续数组。

提示:

  • 1 <= nums.length <= 105
  • 1 <= nums[i] <= 109

解题思路与代码实现

nums数组去重升序排序后,设调整后的数组为newNums,在[newNums[0], newNums[0]+n-1](n为nums数组长度)范围内的元素是不需要调整的,设这个范围内的元素个数为k,则调整次数为n-k。

但枚举每个可能的元素作为调整后的数组元素起始值,这种暴力破解会超时,所以还需要使用滑动窗口。

 public int minOperations(int[] nums) {
        Set<Integer> set = new TreeSet<>(); // 辅助集合,用于去重+升序排序
        for (int i = 0; i < nums.length; i++) {
            set.add(nums[i]);
        }
        List<Integer> sortedList = new ArrayList<>(set);
        int n = nums.length;  // 原数组长度
        int res = Integer.MAX_VALUE;    // 记录最终结果
        int j = 0;  // 和i配合用于计算窗口内覆盖的元素个数
        for (int i = 0; i < sortedList.size(); i++) {  // 循环所有不重复的元素作为左边界left
            int left = sortedList.get(i), right = left + n - 1;    // 窗口范围[left,left+n-1]
            // j会在一轮循环执行过程中,尽可能右移以增加窗口内覆盖的元素个数k = j-i+1 ,这时需要的操作次数为n-k
            while (j < sortedList.size() && sortedList.get(j) <= right) {   // 注意j越界
                // 比较以获得最少操作数
                res = Math.min(res, n - (j - i + 1));
                j++;
            }
        }
        return res;
    }

踩坑点

暴力破解,枚举每个可能的元素作为调整后的数组元素起始值,超时

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值