Skip to content

Commit 5e25e93

Browse files
authored
feat: add solutions to lc problems: No.3224,3228 (#3299)
* No.3224.Minimum Array Changes to Make Differences Equal * No.3228.Maximum Number of Operations to Move Ones to the End
1 parent 25448d6 commit 5e25e93

File tree

21 files changed

+803
-288
lines changed

21 files changed

+803
-288
lines changed

solution/1600-1699/1674.Minimum Moves to Make Array Complementary/README.md

Lines changed: 85 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -76,27 +76,33 @@ nums[3] + nums[0] = 3 + 1 = 4.
7676

7777
### 方法一:差分数组
7878

79-
我们不妨设 $a$ 为 $nums[i]$ 和 $nums[n-i-1]$ 的较小值,设 $b$ 为 $nums[i]$ 和 $nums[n-i-1]$ 的较大值
79+
假设最终的数组中,数对 $\textit{nums}[i]$ 和 $\textit{nums}[n-i-1]$ 的和为 $s$
8080

81-
假设经过替换后,两数之和为 $x$。由题意,我们知道 $x$ 最小值为 $2$,即两个数替换为 $1$;最大值为 $2 \times limit$,即两个数都替换为 $limit$。因此 $x$ 的取值范围是 $[2,... 2 \times limit]$
81+
我们不妨设 $x$ 为 $\textit{nums}[i]$ 和 $\textit{nums}[n-i-1]$ 的较小值,设 $y$ 为 $\textit{nums}[i]$ 和 $\textit{nums}[n-i-1]$ 的较大值
8282

83-
如何求出对于不同的 $x$,需要替换的最少次数呢?
83+
对于每一对数,我们有以下几种情况:
8484

85-
我们分析发现:
85+
- 如果不需要替换,那么 $x + y = s$。
86+
- 如果替换一次,那么 $x + 1 \le s \le y + \textit{limit}$。
87+
- 如果替换两次,那么 $2 \le s \le x$ 或 $y + \textit{limit} + 1 \le s \le 2 \times \textit{limit}$。
8688

87-
- 如果 $x = a + b$,那么我们需要替换的次数为 $0$,即当前的数对已经满足互补的要求;
88-
- 否则如果 $1 + a \le x \le limit + b $,那么我们需要替换的次数为 $1$,即把其中一个数替换即可;
89-
- 否则如果 $2 \le x \le 2 \times limit$,那么我们需要替换的次数为 $2$,即把两个数都替换。
89+
即:
9090

91-
因此,我们可以遍历每一对数,执行如下操作:
91+
- 在 $[2,..x]$ 范围内,需要替换 $2$ 次。
92+
- 在 $[x+1,..x+y-1]$ 范围内,需要替换 $1$ 次。
93+
- 在 $[x+y]$ 时,不需要替换。
94+
- 在 $[x+y+1,..y + \textit{limit}]$ 范围内,需要替换 $1$ 次。
95+
- 在 $[y + \textit{limit} + 1,..2 \times \textit{limit}]$ 范围内,需要替换 $2$ 次。
9296

93-
1. 先将 $[2,... 2 \times limit]$ 范围需要的操作次数加 $2$。
94-
1. 再将 $[1 + a,... limit + b]$ 范围需要的操作次数减 $1$。
95-
1. 最后将 $[a + b,... a + b]$ 范围需要的操作次数减 $1$。
97+
我们枚举每一个数对,利用差分数组,更新每个数对在不同区间范围内的替换次数。
9698

97-
可以发现,这实际上是在对一个连续区间内的元素进行加减操作,因此我们可以使用差分数组来实现
99+
最后,我们求出下标 $2$ 到 $2 \times \textit{limit}$ 的前缀和中的最小值,即为最少的替换次数
98100

99-
时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 为数组 $nums$ 的长度。
101+
时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 为数组 $\textit{nums}$ 的长度。
102+
103+
相似题目:
104+
105+
- [3224. 使差值相等的最少数组改动次数](https://github.com/doocs/leetcode/blob/main/solution/3200-3299/3224.Minimum%20Array%20Changes%20to%20Make%20Differences%20Equal/README.md)
100106

101107
<!-- tabs:start -->
102108

@@ -105,55 +111,44 @@ nums[3] + nums[0] = 3 + 1 = 4.
105111
```python
106112
class Solution:
107113
def minMoves(self, nums: List[int], limit: int) -> int:
108-
d = [0] * (limit * 2 + 2)
114+
d = [0] * (2 * limit + 2)
109115
n = len(nums)
110-
111-
for i in range(n >> 1):
112-
a, b = min(nums[i], nums[n - i - 1]), max(nums[i], nums[n - i - 1])
113-
116+
for i in range(n // 2):
117+
x, y = nums[i], nums[-i - 1]
118+
if x > y:
119+
x, y = y, x
114120
d[2] += 2
115-
d[limit * 2 + 1] -= 2
116-
117-
d[a + 1] -= 1
118-
d[b + limit + 1] += 1
119-
120-
d[a + b] -= 1
121-
d[a + b + 1] += 1
122-
123-
ans, s = n, 0
124-
for v in d[2 : limit * 2 + 1]:
125-
s += v
126-
if ans > s:
127-
ans = s
128-
return ans
121+
d[x + 1] -= 2
122+
d[x + 1] += 1
123+
d[x + y] -= 1
124+
d[x + y + 1] += 1
125+
d[y + limit + 1] -= 1
126+
d[y + limit + 1] += 2
127+
return min(accumulate(d[2:]))
129128
```
130129

131130
#### Java
132131

133132
```java
134133
class Solution {
135134
public int minMoves(int[] nums, int limit) {
135+
int[] d = new int[2 * limit + 2];
136136
int n = nums.length;
137-
int[] d = new int[limit * 2 + 2];
138-
for (int i = 0; i < n >> 1; ++i) {
139-
int a = Math.min(nums[i], nums[n - i - 1]);
140-
int b = Math.max(nums[i], nums[n - i - 1]);
141-
137+
for (int i = 0; i < n / 2; ++i) {
138+
int x = Math.min(nums[i], nums[n - i - 1]);
139+
int y = Math.max(nums[i], nums[n - i - 1]);
142140
d[2] += 2;
143-
d[limit * 2 + 1] -= 2;
144-
145-
d[a + 1] -= 1;
146-
d[b + limit + 1] += 1;
147-
148-
d[a + b] -= 1;
149-
d[a + b + 1] += 1;
141+
d[x + 1] -= 2;
142+
d[x + 1] += 1;
143+
d[x + y] -= 1;
144+
d[x + y + 1] += 1;
145+
d[y + limit + 1] -= 1;
146+
d[y + limit + 1] += 2;
150147
}
151-
int ans = n, s = 0;
152-
for (int i = 2; i <= limit * 2; ++i) {
148+
int ans = n;
149+
for (int i = 2, s = 0; i < d.length; ++i) {
153150
s += d[i];
154-
if (ans > s) {
155-
ans = s;
156-
}
151+
ans = Math.min(ans, s);
157152
}
158153
return ans;
159154
}
@@ -167,26 +162,25 @@ class Solution {
167162
public:
168163
int minMoves(vector<int>& nums, int limit) {
169164
int n = nums.size();
170-
vector<int> d(limit * 2 + 2);
171-
for (int i = 0; i < n >> 1; ++i) {
172-
int a = min(nums[i], nums[n - i - 1]);
173-
int b = max(nums[i], nums[n - i - 1]);
174-
165+
int d[limit * 2 + 2];
166+
memset(d, 0, sizeof(d));
167+
for (int i = 0; i < n / 2; ++i) {
168+
int x = nums[i], y = nums[n - i - 1];
169+
if (x > y) {
170+
swap(x, y);
171+
}
175172
d[2] += 2;
176-
d[limit * 2 + 1] -= 2;
177-
178-
d[a + 1] -= 1;
179-
d[b + limit + 1] += 1;
180-
181-
d[a + b] -= 1;
182-
d[a + b + 1] += 1;
173+
d[x + 1] -= 2;
174+
d[x + 1] += 1;
175+
d[x + y] -= 1;
176+
d[x + y + 1] += 1;
177+
d[y + limit + 1] -= 1;
178+
d[y + limit + 1] += 2;
183179
}
184-
int ans = n, s = 0;
185-
for (int i = 2; i <= limit * 2; ++i) {
180+
int ans = n;
181+
for (int i = 2, s = 0; i <= limit * 2; ++i) {
186182
s += d[i];
187-
if (ans > s) {
188-
ans = s;
189-
}
183+
ans = min(ans, s);
190184
}
191185
return ans;
192186
}
@@ -197,25 +191,25 @@ public:
197191
198192
```go
199193
func minMoves(nums []int, limit int) int {
200-
d := make([]int, limit*2+2)
201194
n := len(nums)
202-
for i := 0; i < n>>1; i++ {
203-
a, b := min(nums[i], nums[n-i-1]), max(nums[i], nums[n-i-1])
195+
d := make([]int, 2*limit+2)
196+
for i := 0; i < n/2; i++ {
197+
x, y := nums[i], nums[n-1-i]
198+
if x > y {
199+
x, y = y, x
200+
}
204201
d[2] += 2
205-
d[limit*2+1] -= 2
206-
207-
d[a+1] -= 1
208-
d[b+limit+1] += 1
209-
210-
d[a+b] -= 1
211-
d[a+b+1] += 1
202+
d[x+1] -= 2
203+
d[x+1] += 1
204+
d[x+y] -= 1
205+
d[x+y+1] += 1
206+
d[y+limit+1] -= 1
207+
d[y+limit+1] += 2
212208
}
213209
ans, s := n, 0
214-
for _, v := range d[2 : limit*2+1] {
215-
s += v
216-
if ans > s {
217-
ans = s
218-
}
210+
for _, x := range d[2:] {
211+
s += x
212+
ans = min(ans, s)
219213
}
220214
return ans
221215
}
@@ -228,25 +222,21 @@ function minMoves(nums: number[], limit: number): number {
228222
const n = nums.length;
229223
const d: number[] = Array(limit * 2 + 2).fill(0);
230224
for (let i = 0; i < n >> 1; ++i) {
231-
const a = Math.min(nums[i], nums[n - i - 1]);
232-
const b = Math.max(nums[i], nums[n - i - 1]);
233-
225+
const x = Math.min(nums[i], nums[n - 1 - i]);
226+
const y = Math.max(nums[i], nums[n - 1 - i]);
234227
d[2] += 2;
235-
d[limit * 2 + 1] -= 2;
236-
237-
d[a + 1] -= 1;
238-
d[b + limit + 1] += 1;
239-
240-
d[a + b] -= 1;
241-
d[a + b + 1] += 1;
228+
d[x + 1] -= 2;
229+
d[x + 1] += 1;
230+
d[x + y] -= 1;
231+
d[x + y + 1] += 1;
232+
d[y + limit + 1] -= 1;
233+
d[y + limit + 1] += 2;
242234
}
243235
let ans = n;
244236
let s = 0;
245-
for (let i = 2; i <= limit * 2; ++i) {
237+
for (let i = 2; i < d.length; ++i) {
246238
s += d[i];
247-
if (ans > s) {
248-
ans = s;
249-
}
239+
ans = Math.min(ans, s);
250240
}
251241
return ans;
252242
}

0 commit comments

Comments
 (0)