目录
[2009. 使数组连续的最少操作数](#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
实现代码与解析:
排序 + 去重 + 双指针
java
class Solution {
public int minOperations(int[] nums) {
int n =nums.length;
// 排序
Arrays.sort(nums);
// 去重
int t = 1;
for (int i = 1; i < n; i++) {
if (nums[i] != nums[i - 1]) {
nums[t++] = nums[i];
}
}
int res = n;
for (int i = 0, j = 0; i < t; i++) {
while (j < t && nums[j] - nums[i] <= n - 1) {
j++;
}
res = Math.min(res, n - (j - i));
}
return res;
}
}
原理思路:
nums
中 最大 元素与 最小 元素的差等于 nums.length - 1,说明,数组中的数,一定是
从最小值连续到最大值且没有重复值。
所以,进行排序和去重。枚举最小值,找出在 nums[i] + n - 1 范围内的个数,不在范围内的就是需要修改的个数。
当然二分也可以求,就是求第一个大于nums[i]+n−1的位置j。
滑动窗口
java
class Solution {
public int minOperations(int[] nums) {
int n =nums.length;
// 排序
Arrays.sort(nums);
// 去重
int t = 1;
for (int i = 1; i < n; i++) {
if (nums[i] != nums[i - 1]) {
nums[t++] = nums[i];
}
}
int res = 0;
int l = 0;
for (int r = 0; r < t; r++) {
while (nums[l] < nums[r] - (n - 1)) {
l++;
}
res = Math.max(res, r - l + 1);
}
return n - res;
}
}
原理思路:
和上面的解法原理相同,只不过这里枚举的最大值,然后不在范围内的通过左端点过滤掉,也就是滑动窗口。