LeetCode 2009. 使数组连续的最少操作数
这个题的思路还是挺奇妙的,一定要注意题目给的条件。
- 首先元素不能重复,那说明对于这道题我们需要对输入进来的数组进行去重,然后在进行操作
- 最大值跟最小值的差不能超过 length - 1,需要注意(后面来说)
首先对数组进行排序去重后,选取一段区间
[
l
,
r
]
[l , r]
[l,r]表示不需要修改的区间,则需要修改的数字有
n
−
(
r
−
l
+
1
)
n - (r - l + 1)
n−(r−l+1)个,这个区间还有
n
u
m
s
[
r
]
−
n
u
m
s
[
l
]
+
1
−
(
(
r
−
l
)
+
1
)
nums[r] - nums[l] + 1 - ((r - l) + 1)
nums[r]−nums[l]+1−((r−l)+1)个数没有出现过(从nums[l] ~ nums[r] 的所有数字, 比如 一段数字2,3,5 那么有 5 - 2 + 1 - (2 - 0 + 1)= 1 个数没有出现 就是4),那么就可以把其他要修改的数字改成这些数字,但是如果没有出现过的数字大于了 剩余需要改变的数字, 那么就说明区间内不满足 条件二, 所以我们枚举区间右端 然后二分区间左端 判断一下
n
u
m
s
[
r
]
−
n
u
m
s
[
l
]
+
1
−
(
(
r
−
l
)
+
1
)
<
=
n
−
(
r
−
l
+
1
)
nums[r] - nums[l] + 1 - ((r - l) + 1) <= n - (r - l + 1)
nums[r]−nums[l]+1−((r−l)+1)<=n−(r−l+1) 化简得
n
u
m
s
[
l
]
>
=
n
u
m
s
[
r
]
−
n
+
1
nums[l] >= nums[r] - n + 1
nums[l]>=nums[r]−n+1
代码(枚举左边 二分右边也可以):
class Solution {
public:
int minOperations(vector<int>& nums) {
int n = nums.size();
sort(nums.begin(), nums.end());
int pos = unique(nums.begin(), nums.end()) - nums.begin();
int ans = INT_MAX;
for(int i = pos - 1; i >= 0; i --){
int l = 0 , r = pos - 1;
while(l < r){
int mid = l + r >> 1;
if(nums[mid] >= nums[i] + 1 - n) r = mid;
else l = mid + 1;
}
ans = min(ans, n - (i - l + 1));
}
return ans;
}
};