Skip to content

Commit 94b04b7

Browse files
authored
feat: add solutions to lc problem: No.3422 (#3956)
No.3422.Minimum Operations to Make Subarray Elements Equal
1 parent 6b4d81c commit 94b04b7

File tree

7 files changed

+566
-0
lines changed

7 files changed

+566
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,224 @@
1+
---
2+
comments: true
3+
difficulty: 中等
4+
edit_url: https://github.com/doocs/leetcode/edit/main/solution/3400-3499/3422.Minimum%20Operations%20to%20Make%20Subarray%20Elements%20Equal/README.md
5+
---
6+
7+
<!-- problem:start -->
8+
9+
# [3422. Minimum Operations to Make Subarray Elements Equal 🔒](https://leetcode.cn/problems/minimum-operations-to-make-subarray-elements-equal)
10+
11+
[English Version](/solution/3400-3499/3422.Minimum%20Operations%20to%20Make%20Subarray%20Elements%20Equal/README_EN.md)
12+
13+
## 题目描述
14+
15+
<!-- description:start -->
16+
17+
<p>You are given an integer array <code>nums</code> and an integer <code>k</code>. You can perform the following operation any number of times:</p>
18+
19+
<ul>
20+
<li>Increase or decrease any element of <code>nums</code> by 1.</li>
21+
</ul>
22+
23+
<p>Return the <strong>minimum</strong> number of operations required to ensure that <strong>at least</strong> one <span data-keyword="subarray">subarray</span> of size <code>k</code> in <code>nums</code> has all elements equal.</p>
24+
25+
<p>&nbsp;</p>
26+
<p><strong class="example">Example 1:</strong></p>
27+
28+
<div class="example-block">
29+
<p><strong>Input:</strong> <span class="example-io">nums = [4,-3,2,1,-4,6], k = 3</span></p>
30+
31+
<p><strong>Output:</strong> <span class="example-io">5</span></p>
32+
33+
<p><strong>Explanation:</strong></p>
34+
35+
<ul>
36+
<li>Use 4 operations to add 4 to <code>nums[1]</code>. The resulting array is <span class="example-io"><code>[4, 1, 2, 1, -4, 6]</code>.</span></li>
37+
<li><span class="example-io">Use 1 operation to subtract 1 from <code>nums[2]</code>. The resulting array is <code>[4, 1, 1, 1, -4, 6]</code>.</span></li>
38+
<li><span class="example-io">The array now contains a subarray <code>[1, 1, 1]</code> of size <code>k = 3</code> with all elements equal. Hence, the answer is 5.</span></li>
39+
</ul>
40+
</div>
41+
42+
<p><strong class="example">Example 2:</strong></p>
43+
44+
<div class="example-block">
45+
<p><strong>Input:</strong> <span class="example-io">nums = [-2,-2,3,1,4], k = 2</span></p>
46+
47+
<p><strong>Output:</strong> <span class="example-io">0</span></p>
48+
49+
<p><strong>Explanation:</strong></p>
50+
51+
<ul>
52+
<li>
53+
<p>The subarray <code>[-2, -2]</code> of size <code>k = 2</code> already contains all equal elements, so no operations are needed. Hence, the answer is 0.</p>
54+
</li>
55+
</ul>
56+
</div>
57+
58+
<p>&nbsp;</p>
59+
<p><strong>Constraints:</strong></p>
60+
61+
<ul>
62+
<li><code>2 &lt;= nums.length &lt;= 10<sup>5</sup></code></li>
63+
<li><code>-10<sup>6</sup> &lt;= nums[i] &lt;= 10<sup>6</sup></code></li>
64+
<li><code>2 &lt;= k &lt;= nums.length</code></li>
65+
</ul>
66+
67+
<!-- description:end -->
68+
69+
## 解法
70+
71+
<!-- solution:start -->
72+
73+
### 方法一:有序集合
74+
75+
根据题目描述,我们需要找到一个长度为 $k$ 的子数组,通过最少的操作使得子数组中的所有元素相等,即我们需要找到一个长度为 $k$ 的子数组,使得子数组中所有元素变成这 $k$ 个元素的中位数所需的最少操作次数最小。
76+
77+
我们可以使用两个有序集合 $l$ 和 $r$ 分别维护 $k$ 个元素的左右两部分,其中 $l$ 用于存储 $k$ 个元素中较小的一部分,$r$ 用于存储 $k$ 个元素中较大的一部分,并且 $l$ 的元素个数要么等于 $r$ 的元素个数,要么比 $r$ 的元素个数少一个,这样 $r$ 的最小值就是 $k$ 个元素中的中位数。
78+
79+
时间复杂度 $O(n \times \log k)$,空间复杂度 $O(k)$。其中 $n$ 为数组 $\textit{nums}$ 的长度。
80+
81+
<!-- tabs:start -->
82+
83+
#### Python3
84+
85+
```python
86+
class Solution:
87+
def minOperations(self, nums: List[int], k: int) -> int:
88+
l = SortedList()
89+
r = SortedList()
90+
s1 = s2 = 0
91+
ans = inf
92+
for i, x in enumerate(nums):
93+
l.add(x)
94+
s1 += x
95+
y = l.pop()
96+
s1 -= y
97+
r.add(y)
98+
s2 += y
99+
if len(r) - len(l) > 1:
100+
y = r.pop(0)
101+
s2 -= y
102+
l.add(y)
103+
s1 += y
104+
if i >= k - 1:
105+
ans = min(ans, s2 - r[0] * len(r) + r[0] * len(l) - s1)
106+
j = i - k + 1
107+
if nums[j] in r:
108+
r.remove(nums[j])
109+
s2 -= nums[j]
110+
else:
111+
l.remove(nums[j])
112+
s1 -= nums[j]
113+
return ans
114+
```
115+
116+
#### Java
117+
118+
```java
119+
class Solution {
120+
public long minOperations(int[] nums, int k) {
121+
TreeMap<Integer, Integer> l = new TreeMap<>();
122+
TreeMap<Integer, Integer> r = new TreeMap<>();
123+
long s1 = 0, s2 = 0;
124+
int sz1 = 0, sz2 = 0;
125+
long ans = Long.MAX_VALUE;
126+
for (int i = 0; i < nums.length; ++i) {
127+
l.merge(nums[i], 1, Integer::sum);
128+
s1 += nums[i];
129+
++sz1;
130+
int y = l.lastKey();
131+
if (l.merge(y, -1, Integer::sum) == 0) {
132+
l.remove(y);
133+
}
134+
s1 -= y;
135+
--sz1;
136+
r.merge(y, 1, Integer::sum);
137+
s2 += y;
138+
++sz2;
139+
if (sz2 - sz1 > 1) {
140+
y = r.firstKey();
141+
if (r.merge(y, -1, Integer::sum) == 0) {
142+
r.remove(y);
143+
}
144+
s2 -= y;
145+
--sz2;
146+
l.merge(y, 1, Integer::sum);
147+
s1 += y;
148+
++sz1;
149+
}
150+
if (i >= k - 1) {
151+
ans = Math.min(ans, s2 - r.firstKey() * sz2 + r.firstKey() * sz1 - s1);
152+
int j = i - k + 1;
153+
if (r.containsKey(nums[j])) {
154+
if (r.merge(nums[j], -1, Integer::sum) == 0) {
155+
r.remove(nums[j]);
156+
}
157+
s2 -= nums[j];
158+
--sz2;
159+
} else {
160+
if (l.merge(nums[j], -1, Integer::sum) == 0) {
161+
l.remove(nums[j]);
162+
}
163+
s1 -= nums[j];
164+
--sz1;
165+
}
166+
}
167+
}
168+
return ans;
169+
}
170+
}
171+
```
172+
173+
#### C++
174+
175+
```cpp
176+
class Solution {
177+
public:
178+
long long minOperations(vector<int>& nums, int k) {
179+
multiset<int> l, r;
180+
long long s1 = 0, s2 = 0, ans = 1e18;
181+
for (int i = 0; i < nums.size(); ++i) {
182+
l.insert(nums[i]);
183+
s1 += nums[i];
184+
int y = *l.rbegin();
185+
l.erase(l.find(y));
186+
s1 -= y;
187+
r.insert(y);
188+
s2 += y;
189+
if (r.size() - l.size() > 1) {
190+
y = *r.begin();
191+
r.erase(r.find(y));
192+
s2 -= y;
193+
l.insert(y);
194+
s1 += y;
195+
}
196+
if (i >= k - 1) {
197+
long long x = *r.begin();
198+
ans = min(ans, s2 - x * (int) r.size() + x * (int) l.size() - s1);
199+
int j = i - k + 1;
200+
if (r.contains(nums[j])) {
201+
r.erase(r.find(nums[j]));
202+
s2 -= nums[j];
203+
} else {
204+
l.erase(l.find(nums[j]));
205+
s1 -= nums[j];
206+
}
207+
}
208+
}
209+
return ans;
210+
}
211+
};
212+
```
213+
214+
#### Go
215+
216+
```go
217+
218+
```
219+
220+
<!-- tabs:end -->
221+
222+
<!-- solution:end -->
223+
224+
<!-- problem:end -->

0 commit comments

Comments
 (0)