题目:
给你一个整数数组 nums
。每一次操作中,你可以将 nums
中 任意 一个元素替换成 任意 整数。
如果 nums
满足以下条件,那么它是 连续的 :
nums
中所有元素都是 互不相同 的。nums
中 最大 元素与 最小 元素的差等于nums.length - 1
。
比方说,nums = [4, 2, 5, 3]
是 连续的 ,但是 nums = [1, 2, 3, 5, 6]
不是连续的 。
请你返回使 nums
连续 的 最少 操作次数。
思考:
- “每次操作是改变nums中的一个元素的值” ----> 数组的长度n不会变
- “要使最终数组变成连续的(元素互不相同且数值连续)” ----> 假设最终的连续数组从left开始,到right为止,那么1.所有数值在[left, right]以外的元素x都需要改变,2.所有数值在[left, right]以内的重复的元素y都需要改变 ----> 所有元素x和y的数量之和res即为答案
- 要使和res最小,就要使[left, right]包含的不重复的元素尽可能多 ----> 先对数组进行去重和排序操作,然后从小到大遍历数组中的元素作为left,则right=left+n-1,计算包含的元素数量,取最大值,然后得到答案res
代码如下:
class Solution(object):def minOperations(self, nums):""":type nums: List[int]:rtype: int"""n = len(nums)sorted_nums = sorted(set(nums)) # 去掉nums中的重复元素,并排序n_ = len(sorted_nums)count = 1for i in range(0, n_):# 从小到大遍历数组中的元素作为leftleft = sorted_nums[i]right = left + n - 1count_ = 1 # 不用操作的元素数量,要尽可能大for j in range(i+1, n_):if sorted_nums[j] > right:breakelse:count_ += 1count = max(count_, count)if count == n:return 0return n - count
超时,卡在 55 / 62 个例子。
优化代码:
由于从小往大取左边界,所以包含在右边界内的最大元素(的下标)也一定逐渐增大,要找到count=j-i+1的最大值。那么将范围[left,right]看成一个滑动窗口,窗口大小不变,找到每次窗口变化后count的最大值即可,代码如下:
class Solution(object):def minOperations(self, nums):""":type nums: List[int]:rtype: int"""n = len(nums)sorted_nums = sorted(set(nums)) # 去掉nums中的重复元素,并排序n_ = len(sorted_nums)count = 0j = 0for i in range(0, n_):# 从小到大遍历数组中的元素作为leftleft = sorted_nums[i]right = left + n - 1while j < n_ and sorted_nums[j] <= right:count = max(count, j - i + 1)j += 1return n - count
提交通过: