2024.4.8
- 题目来源
- 我的题解
- 方法一 去重+排序+滑动窗口
题目来源
力扣每日一题;题序:2009
我的题解
方法一 去重+排序+滑动窗口
参考官方题解。
记数组 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;
}
有任何问题,欢迎评论区交流,欢迎评论区提供其它解题思路(代码),也可以点个赞支持一下作者哈😄~