初学python记录:力扣2009. 使数组连续的最少操作数

文章讨论了如何通过最少的操作次数,将给定的整数数组转换为一个连续的序列,其中所有元素互不相同且最大值与最小值之差等于数组长度减一。通过去重、排序并采用滑动窗口策略找到最优解。
摘要由CSDN通过智能技术生成

题目:

给你一个整数数组 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

提交通过:

  • 7
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值