Skip to content

Commit 89a9166

Browse files
authored
feat: add solutions for lc No.3510 (#4971)
1 parent 31583bd commit 89a9166

6 files changed

Lines changed: 765 additions & 10 deletions

File tree

solution/3500-3599/3510.Minimum Pair Removal to Sort Array II/README.md

Lines changed: 260 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -82,32 +82,287 @@ tags:
8282

8383
<!-- solution:start -->
8484

85-
### 方法一
85+
### 方法一:有序集合
86+
87+
我们定义一个有序集合 $\textit{sl}$ 来存储所有相邻元素对的和及其左侧下标的元组 $(\textit{s}, i)$,定义另一个有序集合 $\textit{idx}$ 来存储当前数组中剩余元素的下标,并使用变量 $\textit{inv}$ 来记录当前数组中的逆序对数量。初始时,我们遍历数组 $\textit{nums}$,将所有相邻元素对的和及其左侧下标的元组加入有序集合 $\textit{sl}$ 中,并计算逆序对数量 $\textit{inv}$。
88+
89+
在每次操作中,我们从有序集合 $\textit{sl}$ 中取出和最小的元素对 $(\textit{s}, i)$,那么我们可以得到下标 $i$ 和 $j$(其中 $j$ 是下标 $i$ 在有序集合 $\textit{idx}$ 中的下一个下标)对应的元素对是当前数组中和最小的相邻元素对。如果 $nums[i] > nums[j]$,则说明该元素对是一个逆序对,合并替换后逆序对数量 $\textit{inv}$ 减一。
90+
91+
接下来,我们需要更新与下标 $i$ 和 $j$ 相关的元素对:
92+
93+
1. 如果下标 $i$ 在有序集合 $\textit{idx}$ 中有前驱下标 $h$,则需要更新元素对 $(h, i)$。如果 $nums[h] > nums[i]$,则说明该元素对是一个逆序对,合并替换后逆序对数量 $\textit{inv}$ 减一。然后,我们从有序集合 $\textit{sl}$ 中移除元素对 $(h, i)$,并将新的元素对 $(h, s)$ 加入有序集合 $\textit{sl}$ 中。如果 $nums[h] > s$,则说明新的元素对是一个逆序对,合并替换后逆序对数量 $\textit{inv}$ 加一。
94+
95+
2. 如果下标 $j$ 在有序集合 $\textit{idx}$ 中有后继下标 $k$,则需要更新元素对 $(j, k)$。如果 $nums[j] > nums[k]$,则说明该元素对是一个逆序对,合并替换后逆序对数量 $\textit{inv}$ 减一。然后,我们从有序集合 $\textit{sl}$ 中移除元素对 $(j, k)$,并将新的元素对 $(s, k)$ 加入有序集合 $\textit{sl}$ 中。如果 $s > nums[k]$,则说明新的元素对是一个逆序对,合并替换后逆序对数量 $\textit{inv}$ 加一。
96+
97+
接下来,我们将下标 $i$ 处的元素替换为 $\textit{s}$,并从有序集合 $\textit{idx}$ 中移除下标 $j$。我们重复上述过程,直到逆序对数量 $\textit{inv}$ 为零为止。最终,操作次数即为将数组变为非递减所需的最小操作次数。
98+
99+
时间复杂度 $O(n \log n)$,空间复杂度 $O(n)$。其中 $n$ 为数组的长度。
86100

87101
<!-- tabs:start -->
88102

89103
#### Python3
90104

91105
```python
92-
106+
class Solution:
107+
def minimumPairRemoval(self, nums: List[int]) -> int:
108+
n = len(nums)
109+
sl = SortedList()
110+
idx = SortedList(range(n))
111+
inv = 0
112+
for i in range(n - 1):
113+
sl.add((nums[i] + nums[i + 1], i))
114+
if nums[i] > nums[i + 1]:
115+
inv += 1
116+
ans = 0
117+
while inv:
118+
ans += 1
119+
s, i = sl.pop(0)
120+
pos = idx.index(i)
121+
j = idx[pos + 1]
122+
if nums[i] > nums[j]:
123+
inv -= 1
124+
if pos > 0:
125+
h = idx[pos - 1]
126+
if nums[h] > nums[i]:
127+
inv -= 1
128+
sl.remove((nums[h] + nums[i], h))
129+
if nums[h] > s:
130+
inv += 1
131+
sl.add((nums[h] + s, h))
132+
if pos + 2 < len(idx):
133+
k = idx[pos + 2]
134+
if nums[j] > nums[k]:
135+
inv -= 1
136+
sl.remove((nums[j] + nums[k], j))
137+
if s > nums[k]:
138+
inv += 1
139+
sl.add((s + nums[k], i))
140+
141+
nums[i] = s
142+
idx.remove(j)
143+
return ans
93144
```
94145

95146
#### Java
96147

97148
```java
98-
149+
class Solution {
150+
record Pair(long s, int i) implements Comparable<Pair> {
151+
@Override
152+
public int compareTo(Pair other) {
153+
int compareS = Long.compare(this.s, other.s);
154+
return compareS != 0 ? compareS : Integer.compare(this.i, other.i);
155+
}
156+
}
157+
158+
public int minimumPairRemoval(int[] nums) {
159+
int n = nums.length;
160+
int inv = 0;
161+
TreeSet<Pair> sl = new TreeSet<>();
162+
for (int i = 0; i < n - 1; ++i) {
163+
if (nums[i] > nums[i + 1]) {
164+
++inv;
165+
}
166+
sl.add(new Pair(nums[i] + nums[i + 1], i));
167+
}
168+
TreeSet<Integer> idx = new TreeSet<>();
169+
long[] arr = new long[n];
170+
for (int i = 0; i < n; ++i) {
171+
idx.add(i);
172+
arr[i] = nums[i];
173+
}
174+
175+
int ans = 0;
176+
while (inv > 0) {
177+
++ans;
178+
var p = sl.pollFirst();
179+
long s = p.s;
180+
int i = p.i;
181+
int j = idx.higher(i);
182+
if (arr[i] > arr[j]) {
183+
--inv;
184+
}
185+
Integer h = idx.lower(i);
186+
if (h != null) {
187+
if (arr[h] > arr[i]) {
188+
--inv;
189+
}
190+
sl.remove(new Pair(arr[h] + arr[i], h));
191+
if (arr[h] > s) {
192+
++inv;
193+
}
194+
sl.add(new Pair(arr[h] + s, h));
195+
}
196+
Integer k = idx.higher(j);
197+
if (k != null) {
198+
if (arr[j] > arr[k]) {
199+
--inv;
200+
}
201+
sl.remove(new Pair(arr[j] + arr[k], j));
202+
if (s > arr[k]) {
203+
++inv;
204+
}
205+
sl.add(new Pair(s + arr[k], i));
206+
}
207+
arr[i] = s;
208+
idx.remove(j);
209+
}
210+
return ans;
211+
}
212+
}
99213
```
100214

101215
#### C++
102216

103217
```cpp
104-
218+
class Solution {
219+
public:
220+
int minimumPairRemoval(vector<int>& nums) {
221+
int n = nums.size();
222+
int inv = 0;
223+
224+
set<pair<long long, int>> sl;
225+
set<int> idx;
226+
vector<long long> arr(nums.begin(), nums.end());
227+
228+
for (int i = 0; i < n; ++i) idx.insert(i);
229+
230+
for (int i = 0; i < n - 1; ++i) {
231+
if (nums[i] > nums[i + 1]) {
232+
++inv;
233+
}
234+
sl.insert({(long long) nums[i] + nums[i + 1], i});
235+
}
236+
237+
int ans = 0;
238+
while (inv > 0) {
239+
++ans;
240+
241+
auto it = sl.begin();
242+
long long s = it->first;
243+
int i = it->second;
244+
sl.erase(it);
245+
246+
auto j_it = idx.upper_bound(i);
247+
int j = *j_it;
248+
249+
if (arr[i] > arr[j]) {
250+
--inv;
251+
}
252+
253+
auto i_it = idx.find(i);
254+
if (i_it != idx.begin()) {
255+
auto h_it = prev(i_it);
256+
int h = *h_it;
257+
258+
if (arr[h] > arr[i]) {
259+
--inv;
260+
}
261+
sl.erase({arr[h] + arr[i], h});
262+
263+
if (arr[h] > s) {
264+
++inv;
265+
}
266+
sl.insert({arr[h] + s, h});
267+
}
268+
269+
auto k_it = next(j_it);
270+
if (k_it != idx.end()) {
271+
int k = *k_it;
272+
273+
if (arr[j] > arr[k]) {
274+
--inv;
275+
}
276+
sl.erase({arr[j] + arr[k], j});
277+
278+
if (s > arr[k]) {
279+
++inv;
280+
}
281+
sl.insert({s + arr[k], i});
282+
}
283+
284+
arr[i] = s;
285+
idx.erase(j);
286+
}
287+
288+
return ans;
289+
}
290+
};
105291
```
106292

107293
#### Go
108294

109295
```go
110-
296+
func minimumPairRemoval(nums []int) (ans int) {
297+
type pair struct{ s, i int }
298+
299+
n := len(nums)
300+
inv := 0
301+
302+
sl := redblacktree.NewWith[pair, struct{}](func(a, b pair) int { return cmp.Or(a.s-b.s, a.i-b.i) })
303+
idx := redblacktree.New[int, struct{}]()
304+
for i := 0; i < n; i++ {
305+
idx.Put(i, struct{}{})
306+
}
307+
308+
for i := 0; i < n-1; i++ {
309+
if nums[i] > nums[i+1] {
310+
inv++
311+
}
312+
sl.Put(pair{nums[i] + nums[i+1], i}, struct{}{})
313+
}
314+
315+
for inv > 0 {
316+
ans++
317+
318+
it := sl.Iterator()
319+
it.First()
320+
p := it.Key()
321+
sl.Remove(p)
322+
323+
s, i := p.s, p.i
324+
325+
jNode, _ := idx.Ceiling(i + 1)
326+
j := jNode.Key
327+
328+
if nums[i] > nums[j] {
329+
inv--
330+
}
331+
332+
if hNode, ok := idx.Floor(i - 1); ok {
333+
h := hNode.Key
334+
335+
if nums[h] > nums[i] {
336+
inv--
337+
}
338+
sl.Remove(pair{nums[h] + nums[i], h})
339+
340+
if nums[h] > s {
341+
inv++
342+
}
343+
sl.Put(pair{nums[h] + s, h}, struct{}{})
344+
}
345+
346+
if kNode, ok := idx.Ceiling(j + 1); ok {
347+
k := kNode.Key
348+
349+
if nums[j] > nums[k] {
350+
inv--
351+
}
352+
sl.Remove(pair{nums[j] + nums[k], j})
353+
354+
if s > nums[k] {
355+
inv++
356+
}
357+
sl.Put(pair{s + nums[k], i}, struct{}{})
358+
}
359+
360+
nums[i] = s
361+
idx.Remove(j)
362+
}
363+
364+
return
365+
}
111366
```
112367

113368
<!-- tabs:end -->

0 commit comments

Comments
 (0)