题目:
给你一个整数数组 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 = 1
for i in range(0, n_):
# 从小到大遍历数组中的元素作为left
left = sorted_nums[i]
right = left + n - 1
count_ = 1 # 不用操作的元素数量,要尽可能大
for j in range(i+1, n_):
if sorted_nums[j] > right:
break
else:
count_ += 1
count = max(count_, count)
if count == n:
return 0
return 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 = 0
j = 0
for i in range(0, n_):
# 从小到大遍历数组中的元素作为left
left = sorted_nums[i]
right = left + n - 1
while j < n_ and sorted_nums[j] <= right:
count = max(count, j - i + 1)
j += 1
return n - count
提交通过: