Skip to content

Commit

Permalink
feat: $2009
Browse files Browse the repository at this point in the history
  • Loading branch information
robot committed Sep 25, 2021
1 parent 16d7f27 commit fc224d0
Show file tree
Hide file tree
Showing 3 changed files with 126 additions and 0 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -514,6 +514,7 @@ leetcode 题解,记录自己的 leetcode 解题之路。
- [1872. 石子游戏 VIII](./problems/1872.stone-game-viii.md)
- [1883. 准时抵达会议现场的最小跳过休息次数](./problems/5775.minimum-skips-to-arrive-at-meeting-on-time.md)
- [1970. 你能穿过矩阵的最后一天](./problems/1970.last-day-where-you-can-still-cross.md)
- [2009. 使数组连续的最少操作数](./problems/2009.minimum-number-of-operations-to-make-array-continuous.md)

## :trident:  anki 卡片

Expand Down
1 change: 1 addition & 0 deletions SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -336,5 +336,6 @@
- [1872. 石子游戏 VIII](./problems/1872.stone-game-viii.md)
- [1883. 准时抵达会议现场的最小跳过休息次数](./problems/5775.minimum-skips-to-arrive-at-meeting-on-time.md)
- [1970. 你能穿过矩阵的最后一天](./problems/1970.last-day-where-you-can-still-cross.md)
- [2009. 使数组连续的最少操作数](./problems/2009.minimum-number-of-operations-to-make-array-continuous.md)

- [后序](epilogue.md)
124 changes: 124 additions & 0 deletions problems/2009.minimum-number-of-operations-to-make-array-continuous.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
## 题目地址(2009. 使数组连续的最少操作数)

https://leetcode-cn.com/problems/minimum-number-of-operations-to-make-array-continuous/

## 题目描述

```
给你一个整数数组 nums 。每一次操作中,你可以将 nums 中 任意 一个元素替换成 任意 整数。
如果 nums 满足以下条件,那么它是 连续的 :
nums 中所有元素都是 互不相同 的。
nums 中 最大 元素与 最小 元素的差等于 nums.length - 1 。
比方说,nums = [4, 2, 5, 3] 是 连续的 ,但是 nums = [1, 2, 3, 5, 6] 不是连续的 。
请你返回使 nums 连续 的 最少 操作次数。
 
示例 1:
输入:nums = [4,2,5,3]
输出:0
解释:nums 已经是连续的了。
示例 2:
输入:nums = [1,2,3,5,6]
输出:1
解释:一个可能的解是将最后一个元素变为 4 。
结果数组为 [1,2,3,5,4] ,是连续数组。
示例 3:
输入:nums = [1,10,100,1000]
输出:3
解释:一个可能的解是:
- 将第二个元素变为 2 。
- 将第三个元素变为 3 。
- 将第四个元素变为 4 。
结果数组为 [1,2,3,4] ,是连续数组。
 
提示:
1 <= nums.length <= 105
1 <= nums[i] <= 109
```

## 前置知识

- 二分

## 公司

- 暂无

## 思路

由于最终的数组长度一定是原数组长度。 因此题目让我们找最少操作数,其实等价于找最多保留多少个数不变,这样我们就可以通过最少的操作数使得数组连续。

朴素的思路是枚举所有的区间 [a,b] 其中 a 和 b 为区间 [min(nums),max(nums)] 中的两个数。这种思路的时间复杂度是 $O(v^2)$,其中 v 为 nums 的值域。看一下数据范围,很明显会超时。

我们可以先对数组排序,这样就可以二分找答案,使得时间复杂度降低。看下时间复杂度排序的时间是可以允许的,因此这种解决可以 ac。

 具体地:

- 对数组去重
- 对数组排序
- 遍历 nums,对于每一个 num 我们都二分找到最左和最右的**满足值域差小于等于 old_n 的索引**,其中 old_n 为去重前的 nums 长度。简单来说,我们需要找到满足值在 [x,num] 范围的最左 x 和满足值在 [num,y] 范围的最右 y
- 满足两个值域范围的区间我们找到了,那么答案区间长度的最大值,也就是 n - 区间长度中的**最小值**

 具体参考下方代码。

## 关键点

- 反向思考,题目要找最少操作数,其实就是找最多保留多少个数

## 代码

- 语言支持:Python3

Python3 Code:

```python

import bisect


class Solution:
def minOperations(self, nums: List[int]) -> int:
ans = on = len(nums)
nums = list(set(nums))
nums.sort()
n = len(nums)
for i, v in enumerate(nums):
r = bisect.bisect_right(nums, v + on - 1)
l = bisect.bisect_left(nums, v - on + 1)
ans = min(ans, n - (r - i), n - (i - l + 1))
return ans + (on - n)

```

**复杂度分析**

令 n 为数组长度。

- 时间复杂度:$O(nlogn)$
- 空间复杂度:$O(n)$

> 此题解由 [力扣刷题插件](https://leetcode-pp.github.io/leetcode-cheat/?tab=solution-template) 自动生成。
力扣的小伙伴可以[关注我](https://leetcode-cn.com/u/fe-lucifer/),这样就会第一时间收到我的动态啦~

以上就是本文的全部内容了。大家对此有何看法,欢迎给我留言,我有时间都会一一查看回答。更多算法套路可以访问我的 LeetCode 题解仓库:https://github.com/azl397985856/leetcode 。 目前已经 40K star 啦。大家也可以关注我的公众号《力扣加加》带你啃下算法这块硬骨头。

关注公众号力扣加加,努力用清晰直白的语言还原解题思路,并且有大量图解,手把手教你识别套路,高效刷题。

![](https://tva1.sinaimg.cn/large/007S8ZIlly1gfcuzagjalj30p00dwabs.jpg)

0 comments on commit fc224d0

Please sign in to comment.