Skip to content

Commit 5f828dc

Browse files
authored
feat: add solutions to lc problem: No.3587 (#4514)
No.3587.Minimum Adjacent Swaps to Alternate Parity
1 parent e59e051 commit 5f828dc

File tree

7 files changed

+406
-8
lines changed

7 files changed

+406
-8
lines changed

solution/3500-3599/3587.Minimum Adjacent Swaps to Alternate Parity/README.md

Lines changed: 141 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -94,32 +94,169 @@ edit_url: https://github.com/doocs/leetcode/edit/main/solution/3500-3599/3587.Mi
9494

9595
<!-- solution:start -->
9696

97-
### 方法一
97+
### 方法一:分类讨论 + 贪心
98+
99+
对于一个有效排列,奇数和偶数的个数只能相差 1 或者相等。因此,如果奇数和偶数的个数相差超过 1,则无法构成有效排列,直接返回 -1。
100+
101+
我们用一个数组 $\text{pos}$ 来存储奇数和偶数的下标,其中 $\text{pos}[0]$ 存储偶数的下标,而 $\text{pos}[1]$ 存储奇数的下标。
102+
103+
如果奇数和偶数的个数相等,则可以有两种有效排列:奇数在偶数前面,或者偶数在奇数前面。我们可以计算这两种排列的交换次数,取最小值。
104+
105+
如果奇数的个数大于偶数的个数,则只有一种有效排列,即奇数在偶数前面。此时,我们只需要计算这种排列的交换次数。
106+
107+
因此,我们定义一个函数 $\text{calc}(k)$,其中 $k$ 表示第一个元素的奇偶性(0 表示偶数,1 表示奇数)。该函数计算从当前排列到以 $k$ 开头的有效排列所需的交换次数。我们只需要遍历 $\text{pos}[k]$ 中的下标,计算每个下标与其在有效排列中的位置之间的差值之和。
108+
109+
时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 是数组 $\text{nums}$ 的长度。
98110

99111
<!-- tabs:start -->
100112

101113
#### Python3
102114

103115
```python
104-
116+
class Solution:
117+
def minSwaps(self, nums: List[int]) -> int:
118+
def calc(k: int) -> int:
119+
return sum(abs(i - j) for i, j in zip(range(0, len(nums), 2), pos[k]))
120+
121+
pos = [[], []]
122+
for i, x in enumerate(nums):
123+
pos[x & 1].append(i)
124+
if abs(len(pos[0]) - len(pos[1])) > 1:
125+
return -1
126+
if len(pos[0]) > len(pos[1]):
127+
return calc(0)
128+
if len(pos[0]) < len(pos[1]):
129+
return calc(1)
130+
return min(calc(0), calc(1))
105131
```
106132

107133
#### Java
108134

109135
```java
110-
136+
class Solution {
137+
private List<Integer>[] pos = new List[2];
138+
private int[] nums;
139+
140+
public int minSwaps(int[] nums) {
141+
this.nums = nums;
142+
Arrays.setAll(pos, k -> new ArrayList<>());
143+
for (int i = 0; i < nums.length; ++i) {
144+
pos[nums[i] & 1].add(i);
145+
}
146+
if (Math.abs(pos[0].size() - pos[1].size()) > 1) {
147+
return -1;
148+
}
149+
if (pos[0].size() > pos[1].size()) {
150+
return calc(0);
151+
}
152+
if (pos[0].size() < pos[1].size()) {
153+
return calc(1);
154+
}
155+
return Math.min(calc(0), calc(1));
156+
}
157+
158+
private int calc(int k) {
159+
int res = 0;
160+
for (int i = 0; i < nums.length; i += 2) {
161+
res += Math.abs(pos[k].get(i / 2) - i);
162+
}
163+
return res;
164+
}
165+
}
111166
```
112167

113168
#### C++
114169

115170
```cpp
116-
171+
class Solution {
172+
public:
173+
int minSwaps(vector<int>& nums) {
174+
vector<int> pos[2];
175+
for (int i = 0; i < nums.size(); ++i) {
176+
pos[nums[i] & 1].push_back(i);
177+
}
178+
if (abs(int(pos[0].size() - pos[1].size())) > 1) {
179+
return -1;
180+
}
181+
auto calc = [&](int k) {
182+
int res = 0;
183+
for (int i = 0; i < nums.size(); i += 2) {
184+
res += abs(pos[k][i / 2] - i);
185+
}
186+
return res;
187+
};
188+
if (pos[0].size() > pos[1].size()) {
189+
return calc(0);
190+
}
191+
if (pos[0].size() < pos[1].size()) {
192+
return calc(1);
193+
}
194+
return min(calc(0), calc(1));
195+
}
196+
};
117197
```
118198
119199
#### Go
120200
121201
```go
202+
func minSwaps(nums []int) int {
203+
pos := [2][]int{}
204+
for i, x := range nums {
205+
pos[x&1] = append(pos[x&1], i)
206+
}
207+
if abs(len(pos[0])-len(pos[1])) > 1 {
208+
return -1
209+
}
210+
calc := func(k int) int {
211+
res := 0
212+
for i := 0; i < len(nums); i += 2 {
213+
res += abs(pos[k][i/2] - i)
214+
}
215+
return res
216+
}
217+
if len(pos[0]) > len(pos[1]) {
218+
return calc(0)
219+
}
220+
if len(pos[0]) < len(pos[1]) {
221+
return calc(1)
222+
}
223+
return min(calc(0), calc(1))
224+
}
225+
226+
func abs(x int) int {
227+
if x < 0 {
228+
return -x
229+
}
230+
return x
231+
}
232+
```
122233

234+
#### TypeScript
235+
236+
```ts
237+
function minSwaps(nums: number[]): number {
238+
const pos: number[][] = [[], []];
239+
for (let i = 0; i < nums.length; ++i) {
240+
pos[nums[i] & 1].push(i);
241+
}
242+
if (Math.abs(pos[0].length - pos[1].length) > 1) {
243+
return -1;
244+
}
245+
const calc = (k: number): number => {
246+
let res = 0;
247+
for (let i = 0; i < nums.length; i += 2) {
248+
res += Math.abs(pos[k][i >> 1] - i);
249+
}
250+
return res;
251+
};
252+
if (pos[0].length > pos[1].length) {
253+
return calc(0);
254+
}
255+
if (pos[0].length < pos[1].length) {
256+
return calc(1);
257+
}
258+
return Math.min(calc(0), calc(1));
259+
}
123260
```
124261

125262
<!-- tabs:end -->

solution/3500-3599/3587.Minimum Adjacent Swaps to Alternate Parity/README_EN.md

Lines changed: 141 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -92,32 +92,169 @@ edit_url: https://github.com/doocs/leetcode/edit/main/solution/3500-3599/3587.Mi
9292

9393
<!-- solution:start -->
9494

95-
### Solution 1
95+
### Solution 1: Case Analysis + Greedy
96+
97+
For a valid arrangement, the number of odd and even numbers can only differ by 1 or be equal. Therefore, if the difference between the number of odd and even numbers is greater than 1, it is impossible to form a valid arrangement, and we should return -1 directly.
98+
99+
We use an array $\text{pos}$ to store the indices of odd and even numbers, where $\text{pos}[0]$ stores the indices of even numbers and $\text{pos}[1]$ stores the indices of odd numbers.
100+
101+
If the number of odd and even numbers is equal, there are two valid arrangements: odd numbers before even numbers, or even numbers before odd numbers. We can calculate the number of swaps required for both arrangements and take the minimum.
102+
103+
If the number of odd numbers is greater than the number of even numbers, there is only one valid arrangement, which is odd numbers before even numbers. In this case, we only need to calculate the number of swaps for this arrangement.
104+
105+
Therefore, we define a function $\text{calc}(k)$, where $k$ indicates the parity of the first element (0 for even, 1 for odd). This function calculates the number of swaps needed to transform the current arrangement into a valid arrangement starting with $k$. We just need to iterate over the indices in $\text{pos}[k]$ and sum the differences between each index and its position in the valid arrangement.
106+
107+
The time complexity is $O(n)$, and the space complexity is $O(n)$, where $n$ is the length of the array $\text{nums}$.
96108

97109
<!-- tabs:start -->
98110

99111
#### Python3
100112

101113
```python
102-
114+
class Solution:
115+
def minSwaps(self, nums: List[int]) -> int:
116+
def calc(k: int) -> int:
117+
return sum(abs(i - j) for i, j in zip(range(0, len(nums), 2), pos[k]))
118+
119+
pos = [[], []]
120+
for i, x in enumerate(nums):
121+
pos[x & 1].append(i)
122+
if abs(len(pos[0]) - len(pos[1])) > 1:
123+
return -1
124+
if len(pos[0]) > len(pos[1]):
125+
return calc(0)
126+
if len(pos[0]) < len(pos[1]):
127+
return calc(1)
128+
return min(calc(0), calc(1))
103129
```
104130

105131
#### Java
106132

107133
```java
108-
134+
class Solution {
135+
private List<Integer>[] pos = new List[2];
136+
private int[] nums;
137+
138+
public int minSwaps(int[] nums) {
139+
this.nums = nums;
140+
Arrays.setAll(pos, k -> new ArrayList<>());
141+
for (int i = 0; i < nums.length; ++i) {
142+
pos[nums[i] & 1].add(i);
143+
}
144+
if (Math.abs(pos[0].size() - pos[1].size()) > 1) {
145+
return -1;
146+
}
147+
if (pos[0].size() > pos[1].size()) {
148+
return calc(0);
149+
}
150+
if (pos[0].size() < pos[1].size()) {
151+
return calc(1);
152+
}
153+
return Math.min(calc(0), calc(1));
154+
}
155+
156+
private int calc(int k) {
157+
int res = 0;
158+
for (int i = 0; i < nums.length; i += 2) {
159+
res += Math.abs(pos[k].get(i / 2) - i);
160+
}
161+
return res;
162+
}
163+
}
109164
```
110165

111166
#### C++
112167

113168
```cpp
114-
169+
class Solution {
170+
public:
171+
int minSwaps(vector<int>& nums) {
172+
vector<int> pos[2];
173+
for (int i = 0; i < nums.size(); ++i) {
174+
pos[nums[i] & 1].push_back(i);
175+
}
176+
if (abs(int(pos[0].size() - pos[1].size())) > 1) {
177+
return -1;
178+
}
179+
auto calc = [&](int k) {
180+
int res = 0;
181+
for (int i = 0; i < nums.size(); i += 2) {
182+
res += abs(pos[k][i / 2] - i);
183+
}
184+
return res;
185+
};
186+
if (pos[0].size() > pos[1].size()) {
187+
return calc(0);
188+
}
189+
if (pos[0].size() < pos[1].size()) {
190+
return calc(1);
191+
}
192+
return min(calc(0), calc(1));
193+
}
194+
};
115195
```
116196
117197
#### Go
118198
119199
```go
200+
func minSwaps(nums []int) int {
201+
pos := [2][]int{}
202+
for i, x := range nums {
203+
pos[x&1] = append(pos[x&1], i)
204+
}
205+
if abs(len(pos[0])-len(pos[1])) > 1 {
206+
return -1
207+
}
208+
calc := func(k int) int {
209+
res := 0
210+
for i := 0; i < len(nums); i += 2 {
211+
res += abs(pos[k][i/2] - i)
212+
}
213+
return res
214+
}
215+
if len(pos[0]) > len(pos[1]) {
216+
return calc(0)
217+
}
218+
if len(pos[0]) < len(pos[1]) {
219+
return calc(1)
220+
}
221+
return min(calc(0), calc(1))
222+
}
223+
224+
func abs(x int) int {
225+
if x < 0 {
226+
return -x
227+
}
228+
return x
229+
}
230+
```
120231

232+
#### TypeScript
233+
234+
```ts
235+
function minSwaps(nums: number[]): number {
236+
const pos: number[][] = [[], []];
237+
for (let i = 0; i < nums.length; ++i) {
238+
pos[nums[i] & 1].push(i);
239+
}
240+
if (Math.abs(pos[0].length - pos[1].length) > 1) {
241+
return -1;
242+
}
243+
const calc = (k: number): number => {
244+
let res = 0;
245+
for (let i = 0; i < nums.length; i += 2) {
246+
res += Math.abs(pos[k][i >> 1] - i);
247+
}
248+
return res;
249+
};
250+
if (pos[0].length > pos[1].length) {
251+
return calc(0);
252+
}
253+
if (pos[0].length < pos[1].length) {
254+
return calc(1);
255+
}
256+
return Math.min(calc(0), calc(1));
257+
}
121258
```
122259

123260
<!-- tabs:end -->
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
class Solution {
2+
public:
3+
int minSwaps(vector<int>& nums) {
4+
vector<int> pos[2];
5+
for (int i = 0; i < nums.size(); ++i) {
6+
pos[nums[i] & 1].push_back(i);
7+
}
8+
if (abs(int(pos[0].size() - pos[1].size())) > 1) {
9+
return -1;
10+
}
11+
auto calc = [&](int k) {
12+
int res = 0;
13+
for (int i = 0; i < nums.size(); i += 2) {
14+
res += abs(pos[k][i / 2] - i);
15+
}
16+
return res;
17+
};
18+
if (pos[0].size() > pos[1].size()) {
19+
return calc(0);
20+
}
21+
if (pos[0].size() < pos[1].size()) {
22+
return calc(1);
23+
}
24+
return min(calc(0), calc(1));
25+
}
26+
};

0 commit comments

Comments
 (0)