Skip to content

Commit 2cd7657

Browse files
authored
feat: add solutions to lc problem: No.1850 (doocs#2137)
No.1850.Minimum Adjacent Swaps to Reach the Kth Smallest Number
1 parent 0cead3d commit 2cd7657

File tree

7 files changed

+694
-3
lines changed

7 files changed

+694
-3
lines changed

solution/1800-1899/1850.Minimum Adjacent Swaps to Reach the Kth Smallest Number/README.md

+245-1
Original file line numberDiff line numberDiff line change
@@ -69,22 +69,266 @@
6969

7070
<!-- 这里可写通用的实现逻辑 -->
7171

72+
**方法一:求下一个排列 + 逆序对**
73+
74+
我们可以调用 $k$ 次 `next_permutation` 函数,得到第 $k$ 个最小妙数 $s$。
75+
76+
接下来,我们只需要计算 $num$ 需要经过多少次交换才能变成 $s$ 即可。
77+
78+
我们先考虑一个简单的情况,即 $num$ 中的数字都不相同。在这种情况下,我们可以直接把 $num$ 中的数字字符映射为下标。例如 $num$ 等于 `"54893"`,而 $s$ 等于 `"98345"`。我们将 $num$ 中的每个数字映射为下标,即:
79+
80+
$$
81+
\begin{aligned}
82+
num[0] &= 5 &\rightarrow& \quad 0 \\
83+
num[1] &= 4 &\rightarrow& \quad 1 \\
84+
num[2] &= 8 &\rightarrow& \quad 2 \\
85+
num[3] &= 9 &\rightarrow& \quad 3 \\
86+
num[4] &= 3 &\rightarrow& \quad 4 \\
87+
\end{aligned}
88+
$$
89+
90+
那么 $s$ 中的每个数字映射为下标,就是 `"32410"`。这样,将 $num$ 变成 $s$ 所需要的交换次数,就等于 $s$ 映射后的下标数组的逆序对数。
91+
92+
如果 $num$ 中存在相同的数字,那么我们可以使用一个数组 $d$ 来记录每个数字出现的下标,其中 $d[i]$ 表示数字 $i$ 出现的下标列表。为了使得交换次数尽可能少,在将 $s$ 映射为下标数组时,我们只需要按顺序贪心地选择 $d$ 中对应数字的下标即可。
93+
94+
最后,我们可以直接使用双重循环来计算逆序对数,也可以使用树状数组来优化。
95+
96+
时间复杂度 $O(n \times (k + n))$,空间复杂度 $O(n)$。其中 $n$ 是 $num$ 的长度。
97+
7298
<!-- tabs:start -->
7399

74100
### **Python3**
75101

76102
<!-- 这里可写当前语言的特殊实现逻辑 -->
77103

78104
```python
79-
105+
class Solution:
106+
def getMinSwaps(self, num: str, k: int) -> int:
107+
def next_permutation(nums: List[str]) -> bool:
108+
n = len(nums)
109+
i = n - 2
110+
while i >= 0 and nums[i] >= nums[i + 1]:
111+
i -= 1
112+
if i < 0:
113+
return False
114+
j = n - 1
115+
while j >= 0 and nums[j] <= nums[i]:
116+
j -= 1
117+
nums[i], nums[j] = nums[j], nums[i]
118+
nums[i + 1 : n] = nums[i + 1 : n][::-1]
119+
return True
120+
121+
s = list(num)
122+
for _ in range(k):
123+
next_permutation(s)
124+
d = [[] for _ in range(10)]
125+
idx = [0] * 10
126+
n = len(s)
127+
for i, c in enumerate(num):
128+
j = ord(c) - ord("0")
129+
d[j].append(i)
130+
arr = [0] * n
131+
for i, c in enumerate(s):
132+
j = ord(c) - ord("0")
133+
arr[i] = d[j][idx[j]]
134+
idx[j] += 1
135+
return sum(arr[j] > arr[i] for i in range(n) for j in range(i))
80136
```
81137

82138
### **Java**
83139

84140
<!-- 这里可写当前语言的特殊实现逻辑 -->
85141

86142
```java
143+
class Solution {
144+
public int getMinSwaps(String num, int k) {
145+
char[] s = num.toCharArray();
146+
for (int i = 0; i < k; ++i) {
147+
nextPermutation(s);
148+
}
149+
List<Integer>[] d = new List[10];
150+
Arrays.setAll(d, i -> new ArrayList<>());
151+
int n = s.length;
152+
for (int i = 0; i < n; ++i) {
153+
d[num.charAt(i) - '0'].add(i);
154+
}
155+
int[] idx = new int[10];
156+
int[] arr = new int[n];
157+
for (int i = 0; i < n; ++i) {
158+
arr[i] = d[s[i] - '0'].get(idx[s[i] - '0']++);
159+
}
160+
int ans = 0;
161+
for (int i = 0; i < n; ++i) {
162+
for (int j = 0; j < i; ++j) {
163+
if (arr[j] > arr[i]) {
164+
++ans;
165+
}
166+
}
167+
}
168+
return ans;
169+
}
170+
171+
private boolean nextPermutation(char[] nums) {
172+
int n = nums.length;
173+
int i = n - 2;
174+
while (i >= 0 && nums[i] >= nums[i + 1]) {
175+
--i;
176+
}
177+
if (i < 0) {
178+
return false;
179+
}
180+
int j = n - 1;
181+
while (j >= 0 && nums[i] >= nums[j]) {
182+
--j;
183+
}
184+
swap(nums, i++, j);
185+
for (j = n - 1; i < j; ++i, --j) {
186+
swap(nums, i, j);
187+
}
188+
return true;
189+
}
190+
191+
private void swap(char[] nums, int i, int j) {
192+
char t = nums[i];
193+
nums[i] = nums[j];
194+
nums[j] = t;
195+
}
196+
}
197+
```
198+
199+
### **C++**
200+
201+
```cpp
202+
class Solution {
203+
public:
204+
int getMinSwaps(string num, int k) {
205+
string s = num;
206+
for (int i = 0; i < k; ++i) {
207+
next_permutation(begin(s), end(num));
208+
}
209+
vector<int> d[10];
210+
int n = num.size();
211+
for (int i = 0; i < n; ++i) {
212+
d[num[i] - '0'].push_back(i);
213+
}
214+
int idx[10]{};
215+
vector<int> arr(n);
216+
for (int i = 0; i < n; ++i) {
217+
arr[i] = d[s[i] - '0'][idx[s[i] - '0']++];
218+
}
219+
int ans = 0;
220+
for (int i = 0; i < n; ++i) {
221+
for (int j = 0; j < i; ++j) {
222+
if (arr[j] > arr[i]) {
223+
++ans;
224+
}
225+
}
226+
}
227+
return ans;
228+
}
229+
};
230+
```
231+
232+
### **Go**
233+
234+
```go
235+
func getMinSwaps(num string, k int) (ans int) {
236+
s := []byte(num)
237+
for ; k > 0; k-- {
238+
nextPermutation(s)
239+
}
240+
d := [10][]int{}
241+
for i, c := range num {
242+
j := int(c - '0')
243+
d[j] = append(d[j], i)
244+
}
245+
idx := [10]int{}
246+
n := len(s)
247+
arr := make([]int, n)
248+
for i, c := range s {
249+
j := int(c - '0')
250+
arr[i] = d[j][idx[j]]
251+
idx[j]++
252+
}
253+
for i := 0; i < n; i++ {
254+
for j := 0; j < i; j++ {
255+
if arr[j] > arr[i] {
256+
ans++
257+
}
258+
}
259+
}
260+
return
261+
}
262+
263+
func nextPermutation(nums []byte) bool {
264+
n := len(nums)
265+
i := n - 2
266+
for i >= 0 && nums[i] >= nums[i+1] {
267+
i--
268+
}
269+
if i < 0 {
270+
return false
271+
}
272+
j := n - 1
273+
for j >= 0 && nums[j] <= nums[i] {
274+
j--
275+
}
276+
nums[i], nums[j] = nums[j], nums[i]
277+
for i, j = i+1, n-1; i < j; i, j = i+1, j-1 {
278+
nums[i], nums[j] = nums[j], nums[i]
279+
}
280+
return true
281+
}
282+
```
87283

284+
### **TypeScript**
285+
286+
```ts
287+
function getMinSwaps(num: string, k: number): number {
288+
const n = num.length;
289+
const s = num.split('');
290+
for (let i = 0; i < k; ++i) {
291+
nextPermutation(s);
292+
}
293+
const d: number[][] = Array.from({ length: 10 }, () => []);
294+
for (let i = 0; i < n; ++i) {
295+
d[+num[i]].push(i);
296+
}
297+
const idx: number[] = Array(10).fill(0);
298+
const arr: number[] = [];
299+
for (let i = 0; i < n; ++i) {
300+
arr.push(d[+s[i]][idx[+s[i]]++]);
301+
}
302+
let ans = 0;
303+
for (let i = 0; i < n; ++i) {
304+
for (let j = 0; j < i; ++j) {
305+
if (arr[j] > arr[i]) {
306+
ans++;
307+
}
308+
}
309+
}
310+
return ans;
311+
}
312+
313+
function nextPermutation(nums: string[]): boolean {
314+
const n = nums.length;
315+
let i = n - 2;
316+
while (i >= 0 && nums[i] >= nums[i + 1]) {
317+
i--;
318+
}
319+
if (i < 0) {
320+
return false;
321+
}
322+
let j = n - 1;
323+
while (j >= 0 && nums[i] >= nums[j]) {
324+
j--;
325+
}
326+
[nums[i], nums[j]] = [nums[j], nums[i]];
327+
for (i = i + 1, j = n - 1; i < j; ++i, --j) {
328+
[nums[i], nums[j]] = [nums[j], nums[i]];
329+
}
330+
return true;
331+
}
88332
```
89333

90334
### **...**

0 commit comments

Comments
 (0)