本文主要是介绍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++) { // 循环所有不重复的元素作为左边界leftint left = sortedList.get(i), right = left + n - 1; // 窗口范围[left,left+n-1]// j会在一轮循环执行过程中,尽可能右移以增加窗口内覆盖的元素个数k = j-i+1 ,这时需要的操作次数为n-kwhile (j < sortedList.size() && sortedList.get(j) <= right) { // 注意j越界// 比较以获得最少操作数res = Math.min(res, n - (j - i + 1));j++;}}return res;}
踩坑点
暴力破解,枚举每个可能的元素作为调整后的数组元素起始值,超时
这篇关于2009. 使数组连续的最少操作数的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!