From afb23f0ce1e12b4198a39e01593a0bcbf673adf3 Mon Sep 17 00:00:00 2001 From: yanglbme Date: Thu, 16 Jan 2025 09:58:57 +0800 Subject: [PATCH] feat: add solutions to lc problem: No.3422 No.3422.Minimum Operations to Make Subarray Elements Equal --- .../README.md | 224 ++++++++++++++++++ .../README_EN.md | 224 ++++++++++++++++++ .../Solution.cpp | 36 +++ .../Solution.java | 52 ++++ .../Solution.py | 28 +++ solution/README.md | 1 + solution/README_EN.md | 1 + 7 files changed, 566 insertions(+) create mode 100644 solution/3400-3499/3422.Minimum Operations to Make Subarray Elements Equal/README.md create mode 100644 solution/3400-3499/3422.Minimum Operations to Make Subarray Elements Equal/README_EN.md create mode 100644 solution/3400-3499/3422.Minimum Operations to Make Subarray Elements Equal/Solution.cpp create mode 100644 solution/3400-3499/3422.Minimum Operations to Make Subarray Elements Equal/Solution.java create mode 100644 solution/3400-3499/3422.Minimum Operations to Make Subarray Elements Equal/Solution.py diff --git a/solution/3400-3499/3422.Minimum Operations to Make Subarray Elements Equal/README.md b/solution/3400-3499/3422.Minimum Operations to Make Subarray Elements Equal/README.md new file mode 100644 index 0000000000000..063c164ac9244 --- /dev/null +++ b/solution/3400-3499/3422.Minimum Operations to Make Subarray Elements Equal/README.md @@ -0,0 +1,224 @@ +--- +comments: true +difficulty: 中等 +edit_url: https://github.com/doocs/leetcode/edit/main/solution/3400-3499/3422.Minimum%20Operations%20to%20Make%20Subarray%20Elements%20Equal/README.md +--- + + + +# [3422. Minimum Operations to Make Subarray Elements Equal 🔒](https://leetcode.cn/problems/minimum-operations-to-make-subarray-elements-equal) + +[English Version](/solution/3400-3499/3422.Minimum%20Operations%20to%20Make%20Subarray%20Elements%20Equal/README_EN.md) + +## 题目描述 + + + +

You are given an integer array nums and an integer k. You can perform the following operation any number of times:

+ + + +

Return the minimum number of operations required to ensure that at least one subarray of size k in nums has all elements equal.

+ +

 

+

Example 1:

+ +
+

Input: nums = [4,-3,2,1,-4,6], k = 3

+ +

Output: 5

+ +

Explanation:

+ + +
+ +

Example 2:

+ +
+

Input: nums = [-2,-2,3,1,4], k = 2

+ +

Output: 0

+ +

Explanation:

+ + +
+ +

 

+

Constraints:

+ + + + + +## 解法 + + + +### 方法一:有序集合 + +根据题目描述,我们需要找到一个长度为 $k$ 的子数组,通过最少的操作使得子数组中的所有元素相等,即我们需要找到一个长度为 $k$ 的子数组,使得子数组中所有元素变成这 $k$ 个元素的中位数所需的最少操作次数最小。 + +我们可以使用两个有序集合 $l$ 和 $r$ 分别维护 $k$ 个元素的左右两部分,其中 $l$ 用于存储 $k$ 个元素中较小的一部分,$r$ 用于存储 $k$ 个元素中较大的一部分,并且 $l$ 的元素个数要么等于 $r$ 的元素个数,要么比 $r$ 的元素个数少一个,这样 $r$ 的最小值就是 $k$ 个元素中的中位数。 + +时间复杂度 $O(n \times \log k)$,空间复杂度 $O(k)$。其中 $n$ 为数组 $\textit{nums}$ 的长度。 + + + +#### Python3 + +```python +class Solution: + def minOperations(self, nums: List[int], k: int) -> int: + l = SortedList() + r = SortedList() + s1 = s2 = 0 + ans = inf + for i, x in enumerate(nums): + l.add(x) + s1 += x + y = l.pop() + s1 -= y + r.add(y) + s2 += y + if len(r) - len(l) > 1: + y = r.pop(0) + s2 -= y + l.add(y) + s1 += y + if i >= k - 1: + ans = min(ans, s2 - r[0] * len(r) + r[0] * len(l) - s1) + j = i - k + 1 + if nums[j] in r: + r.remove(nums[j]) + s2 -= nums[j] + else: + l.remove(nums[j]) + s1 -= nums[j] + return ans +``` + +#### Java + +```java +class Solution { + public long minOperations(int[] nums, int k) { + TreeMap l = new TreeMap<>(); + TreeMap r = new TreeMap<>(); + long s1 = 0, s2 = 0; + int sz1 = 0, sz2 = 0; + long ans = Long.MAX_VALUE; + for (int i = 0; i < nums.length; ++i) { + l.merge(nums[i], 1, Integer::sum); + s1 += nums[i]; + ++sz1; + int y = l.lastKey(); + if (l.merge(y, -1, Integer::sum) == 0) { + l.remove(y); + } + s1 -= y; + --sz1; + r.merge(y, 1, Integer::sum); + s2 += y; + ++sz2; + if (sz2 - sz1 > 1) { + y = r.firstKey(); + if (r.merge(y, -1, Integer::sum) == 0) { + r.remove(y); + } + s2 -= y; + --sz2; + l.merge(y, 1, Integer::sum); + s1 += y; + ++sz1; + } + if (i >= k - 1) { + ans = Math.min(ans, s2 - r.firstKey() * sz2 + r.firstKey() * sz1 - s1); + int j = i - k + 1; + if (r.containsKey(nums[j])) { + if (r.merge(nums[j], -1, Integer::sum) == 0) { + r.remove(nums[j]); + } + s2 -= nums[j]; + --sz2; + } else { + if (l.merge(nums[j], -1, Integer::sum) == 0) { + l.remove(nums[j]); + } + s1 -= nums[j]; + --sz1; + } + } + } + return ans; + } +} +``` + +#### C++ + +```cpp +class Solution { +public: + long long minOperations(vector& nums, int k) { + multiset l, r; + long long s1 = 0, s2 = 0, ans = 1e18; + for (int i = 0; i < nums.size(); ++i) { + l.insert(nums[i]); + s1 += nums[i]; + int y = *l.rbegin(); + l.erase(l.find(y)); + s1 -= y; + r.insert(y); + s2 += y; + if (r.size() - l.size() > 1) { + y = *r.begin(); + r.erase(r.find(y)); + s2 -= y; + l.insert(y); + s1 += y; + } + if (i >= k - 1) { + long long x = *r.begin(); + ans = min(ans, s2 - x * (int) r.size() + x * (int) l.size() - s1); + int j = i - k + 1; + if (r.contains(nums[j])) { + r.erase(r.find(nums[j])); + s2 -= nums[j]; + } else { + l.erase(l.find(nums[j])); + s1 -= nums[j]; + } + } + } + return ans; + } +}; +``` + +#### Go + +```go + +``` + + + + + + diff --git a/solution/3400-3499/3422.Minimum Operations to Make Subarray Elements Equal/README_EN.md b/solution/3400-3499/3422.Minimum Operations to Make Subarray Elements Equal/README_EN.md new file mode 100644 index 0000000000000..4b0ce044bf85b --- /dev/null +++ b/solution/3400-3499/3422.Minimum Operations to Make Subarray Elements Equal/README_EN.md @@ -0,0 +1,224 @@ +--- +comments: true +difficulty: Medium +edit_url: https://github.com/doocs/leetcode/edit/main/solution/3400-3499/3422.Minimum%20Operations%20to%20Make%20Subarray%20Elements%20Equal/README_EN.md +--- + + + +# [3422. Minimum Operations to Make Subarray Elements Equal 🔒](https://leetcode.com/problems/minimum-operations-to-make-subarray-elements-equal) + +[中文文档](/solution/3400-3499/3422.Minimum%20Operations%20to%20Make%20Subarray%20Elements%20Equal/README.md) + +## Description + + + +

You are given an integer array nums and an integer k. You can perform the following operation any number of times:

+ +
    +
  • Increase or decrease any element of nums by 1.
  • +
+ +

Return the minimum number of operations required to ensure that at least one subarray of size k in nums has all elements equal.

+ +

 

+

Example 1:

+ +
+

Input: nums = [4,-3,2,1,-4,6], k = 3

+ +

Output: 5

+ +

Explanation:

+ +
    +
  • Use 4 operations to add 4 to nums[1]. The resulting array is [4, 1, 2, 1, -4, 6].
  • +
  • Use 1 operation to subtract 1 from nums[2]. The resulting array is [4, 1, 1, 1, -4, 6].
  • +
  • The array now contains a subarray [1, 1, 1] of size k = 3 with all elements equal. Hence, the answer is 5.
  • +
+
+ +

Example 2:

+ +
+

Input: nums = [-2,-2,3,1,4], k = 2

+ +

Output: 0

+ +

Explanation:

+ +
    +
  • +

    The subarray [-2, -2] of size k = 2 already contains all equal elements, so no operations are needed. Hence, the answer is 0.

    +
  • +
+
+ +

 

+

Constraints:

+ +
    +
  • 2 <= nums.length <= 105
  • +
  • -106 <= nums[i] <= 106
  • +
  • 2 <= k <= nums.length
  • +
+ + + +## Solutions + + + +### Solution 1: Ordered Set + +According to the problem description, we need to find a subarray of length $k$ and make all elements in the subarray equal with the minimum number of operations. That is, we need to find a subarray of length $k$ such that the minimum number of operations required to make all elements in the subarray equal to the median of these $k$ elements is minimized. + +We can use two ordered sets $l$ and $r$ to maintain the left and right parts of the $k$ elements, respectively. $l$ is used to store the smaller part of the $k$ elements, and $r$ is used to store the larger part of the $k$ elements. The number of elements in $l$ is either equal to the number of elements in $r$ or one less than the number of elements in $r$, so the minimum value in $r$ is the median of the $k$ elements. + +The time complexity is $O(n \times \log k)$, and the space complexity is $O(k)$. Here, $n$ is the length of the array $\textit{nums}$. + + + +#### Python3 + +```python +class Solution: + def minOperations(self, nums: List[int], k: int) -> int: + l = SortedList() + r = SortedList() + s1 = s2 = 0 + ans = inf + for i, x in enumerate(nums): + l.add(x) + s1 += x + y = l.pop() + s1 -= y + r.add(y) + s2 += y + if len(r) - len(l) > 1: + y = r.pop(0) + s2 -= y + l.add(y) + s1 += y + if i >= k - 1: + ans = min(ans, s2 - r[0] * len(r) + r[0] * len(l) - s1) + j = i - k + 1 + if nums[j] in r: + r.remove(nums[j]) + s2 -= nums[j] + else: + l.remove(nums[j]) + s1 -= nums[j] + return ans +``` + +#### Java + +```java +class Solution { + public long minOperations(int[] nums, int k) { + TreeMap l = new TreeMap<>(); + TreeMap r = new TreeMap<>(); + long s1 = 0, s2 = 0; + int sz1 = 0, sz2 = 0; + long ans = Long.MAX_VALUE; + for (int i = 0; i < nums.length; ++i) { + l.merge(nums[i], 1, Integer::sum); + s1 += nums[i]; + ++sz1; + int y = l.lastKey(); + if (l.merge(y, -1, Integer::sum) == 0) { + l.remove(y); + } + s1 -= y; + --sz1; + r.merge(y, 1, Integer::sum); + s2 += y; + ++sz2; + if (sz2 - sz1 > 1) { + y = r.firstKey(); + if (r.merge(y, -1, Integer::sum) == 0) { + r.remove(y); + } + s2 -= y; + --sz2; + l.merge(y, 1, Integer::sum); + s1 += y; + ++sz1; + } + if (i >= k - 1) { + ans = Math.min(ans, s2 - r.firstKey() * sz2 + r.firstKey() * sz1 - s1); + int j = i - k + 1; + if (r.containsKey(nums[j])) { + if (r.merge(nums[j], -1, Integer::sum) == 0) { + r.remove(nums[j]); + } + s2 -= nums[j]; + --sz2; + } else { + if (l.merge(nums[j], -1, Integer::sum) == 0) { + l.remove(nums[j]); + } + s1 -= nums[j]; + --sz1; + } + } + } + return ans; + } +} +``` + +#### C++ + +```cpp +class Solution { +public: + long long minOperations(vector& nums, int k) { + multiset l, r; + long long s1 = 0, s2 = 0, ans = 1e18; + for (int i = 0; i < nums.size(); ++i) { + l.insert(nums[i]); + s1 += nums[i]; + int y = *l.rbegin(); + l.erase(l.find(y)); + s1 -= y; + r.insert(y); + s2 += y; + if (r.size() - l.size() > 1) { + y = *r.begin(); + r.erase(r.find(y)); + s2 -= y; + l.insert(y); + s1 += y; + } + if (i >= k - 1) { + long long x = *r.begin(); + ans = min(ans, s2 - x * (int) r.size() + x * (int) l.size() - s1); + int j = i - k + 1; + if (r.contains(nums[j])) { + r.erase(r.find(nums[j])); + s2 -= nums[j]; + } else { + l.erase(l.find(nums[j])); + s1 -= nums[j]; + } + } + } + return ans; + } +}; +``` + +#### Go + +```go + +``` + + + + + + diff --git a/solution/3400-3499/3422.Minimum Operations to Make Subarray Elements Equal/Solution.cpp b/solution/3400-3499/3422.Minimum Operations to Make Subarray Elements Equal/Solution.cpp new file mode 100644 index 0000000000000..7bb9e1937544c --- /dev/null +++ b/solution/3400-3499/3422.Minimum Operations to Make Subarray Elements Equal/Solution.cpp @@ -0,0 +1,36 @@ +class Solution { +public: + long long minOperations(vector& nums, int k) { + multiset l, r; + long long s1 = 0, s2 = 0, ans = 1e18; + for (int i = 0; i < nums.size(); ++i) { + l.insert(nums[i]); + s1 += nums[i]; + int y = *l.rbegin(); + l.erase(l.find(y)); + s1 -= y; + r.insert(y); + s2 += y; + if (r.size() - l.size() > 1) { + y = *r.begin(); + r.erase(r.find(y)); + s2 -= y; + l.insert(y); + s1 += y; + } + if (i >= k - 1) { + long long x = *r.begin(); + ans = min(ans, s2 - x * (int) r.size() + x * (int) l.size() - s1); + int j = i - k + 1; + if (r.contains(nums[j])) { + r.erase(r.find(nums[j])); + s2 -= nums[j]; + } else { + l.erase(l.find(nums[j])); + s1 -= nums[j]; + } + } + } + return ans; + } +}; diff --git a/solution/3400-3499/3422.Minimum Operations to Make Subarray Elements Equal/Solution.java b/solution/3400-3499/3422.Minimum Operations to Make Subarray Elements Equal/Solution.java new file mode 100644 index 0000000000000..e5a4ac7db28af --- /dev/null +++ b/solution/3400-3499/3422.Minimum Operations to Make Subarray Elements Equal/Solution.java @@ -0,0 +1,52 @@ +class Solution { + public long minOperations(int[] nums, int k) { + TreeMap l = new TreeMap<>(); + TreeMap r = new TreeMap<>(); + long s1 = 0, s2 = 0; + int sz1 = 0, sz2 = 0; + long ans = Long.MAX_VALUE; + for (int i = 0; i < nums.length; ++i) { + l.merge(nums[i], 1, Integer::sum); + s1 += nums[i]; + ++sz1; + int y = l.lastKey(); + if (l.merge(y, -1, Integer::sum) == 0) { + l.remove(y); + } + s1 -= y; + --sz1; + r.merge(y, 1, Integer::sum); + s2 += y; + ++sz2; + if (sz2 - sz1 > 1) { + y = r.firstKey(); + if (r.merge(y, -1, Integer::sum) == 0) { + r.remove(y); + } + s2 -= y; + --sz2; + l.merge(y, 1, Integer::sum); + s1 += y; + ++sz1; + } + if (i >= k - 1) { + ans = Math.min(ans, s2 - r.firstKey() * sz2 + r.firstKey() * sz1 - s1); + int j = i - k + 1; + if (r.containsKey(nums[j])) { + if (r.merge(nums[j], -1, Integer::sum) == 0) { + r.remove(nums[j]); + } + s2 -= nums[j]; + --sz2; + } else { + if (l.merge(nums[j], -1, Integer::sum) == 0) { + l.remove(nums[j]); + } + s1 -= nums[j]; + --sz1; + } + } + } + return ans; + } +} diff --git a/solution/3400-3499/3422.Minimum Operations to Make Subarray Elements Equal/Solution.py b/solution/3400-3499/3422.Minimum Operations to Make Subarray Elements Equal/Solution.py new file mode 100644 index 0000000000000..4067339eacb37 --- /dev/null +++ b/solution/3400-3499/3422.Minimum Operations to Make Subarray Elements Equal/Solution.py @@ -0,0 +1,28 @@ +class Solution: + def minOperations(self, nums: List[int], k: int) -> int: + l = SortedList() + r = SortedList() + s1 = s2 = 0 + ans = inf + for i, x in enumerate(nums): + l.add(x) + s1 += x + y = l.pop() + s1 -= y + r.add(y) + s2 += y + if len(r) - len(l) > 1: + y = r.pop(0) + s2 -= y + l.add(y) + s1 += y + if i >= k - 1: + ans = min(ans, s2 - r[0] * len(r) + r[0] * len(l) - s1) + j = i - k + 1 + if nums[j] in r: + r.remove(nums[j]) + s2 -= nums[j] + else: + l.remove(nums[j]) + s1 -= nums[j] + return ans diff --git a/solution/README.md b/solution/README.md index 908e0f42f3d20..9e5e9333ca9a2 100644 --- a/solution/README.md +++ b/solution/README.md @@ -3432,6 +3432,7 @@ | 3419 | [图的最大边权的最小值](/solution/3400-3499/3419.Minimize%20the%20Maximum%20Edge%20Weight%20of%20Graph/README.md) | | 中等 | 第 432 场周赛 | | 3420 | [统计 K 次操作以内得到非递减子数组的数目](/solution/3400-3499/3420.Count%20Non-Decreasing%20Subarrays%20After%20K%20Operations/README.md) | | 困难 | 第 432 场周赛 | | 3421 | [查找进步的学生](/solution/3400-3499/3421.Find%20Students%20Who%20Improved/README.md) | | 中等 | | +| 3422 | [Minimum Operations to Make Subarray Elements Equal](/solution/3400-3499/3422.Minimum%20Operations%20to%20Make%20Subarray%20Elements%20Equal/README.md) | | 中等 | 🔒 | ## 版权 diff --git a/solution/README_EN.md b/solution/README_EN.md index 6b3b052ba1a0c..8c913ea30f7bc 100644 --- a/solution/README_EN.md +++ b/solution/README_EN.md @@ -3430,6 +3430,7 @@ Press Control + F(or Command + F on | 3419 | [Minimize the Maximum Edge Weight of Graph](/solution/3400-3499/3419.Minimize%20the%20Maximum%20Edge%20Weight%20of%20Graph/README_EN.md) | | Medium | Weekly Contest 432 | | 3420 | [Count Non-Decreasing Subarrays After K Operations](/solution/3400-3499/3420.Count%20Non-Decreasing%20Subarrays%20After%20K%20Operations/README_EN.md) | | Hard | Weekly Contest 432 | | 3421 | [Find Students Who Improved](/solution/3400-3499/3421.Find%20Students%20Who%20Improved/README_EN.md) | | Medium | | +| 3422 | [Minimum Operations to Make Subarray Elements Equal](/solution/3400-3499/3422.Minimum%20Operations%20to%20Make%20Subarray%20Elements%20Equal/README_EN.md) | | Medium | 🔒 | ## Copyright