2024.4.8
题目来源
我的题解
方法一 去重+排序+滑动窗口
参考官方题解。
记数组 nums的长度为 n。经过若干次操作后,若数组变为连续的,那么数组的长度不会改变,仍然为 n,且数组最大值与最小值之差为 n−1,所有元素均不相同。可以反向考虑,假设最后连续的数组的最小值为 left,则最大值 right=left+n−1。原数组 nums 中,如果有位于 [left,right]中的,如果只出现一次,可以对其进行保留;多次出现时,则需要对其进行操作;不在这个区间的数字,也需要对其进行操作,将它们变成其他数字来对这个区间进行补足。因此,需要统计原数组 nums中,位于区间 [left,right]内不同的数字个数 k,而 n−k 就是需要进行的操作数。
接下来就是需要确定 left,可以将原数组 nums 所有不同的数字作为 left的候选值,分别计算出 n−k,然后求出最小值。这样的话,可以先将原数字进行去重后排序,然后利用滑动窗口。滑动窗口左端点的值作为 left,然后向右扩展右端点,窗口的长度即为 k,求出所有可能性下最小的 n−k 即可。
时间复杂度:O(n×logn),其中 n 是数组 nums 的长度。排序消耗 O(n×logn),滑动窗口消耗 O(n)。
空间复杂度:O(n)
public int minOperations(int[] nums) {
Set<Integer> set=new HashSet<>();
int n=nums.length;
for(int i=0;i<n;i++){
set.add(nums[i]);
}
List<Integer> list=new ArrayList<>(set);
list.sort((a,b)->a-b);
int count=0;
int res=n;
for(int i=0;i<list.size();i++){
int left=list.get(i);
int right=left+n-1;
//移动窗口
while(count<list.size()&&list.get(count)<=right){
res=Math.min(res,n-(count-i+1));
count++;
}
}
return res;
}
有任何问题,欢迎评论区交流,欢迎评论区提供其它解题思路(代码),也可以点个赞支持一下作者哈😄~