
题目描述
给你一个由 互不相同 的正整数组成的数组 nums
,需要根据每个数字的数位和(即每一位数字相加求和)按 升序 对数组进行排序。如果两个数字的数位和相等,则较小的数字排在前面。
返回将 nums
排列为上述排序顺序所需的 最小 交换次数。
一次 交换 定义为交换数组中两个不同位置的值。
示例 1:
输入: nums = [37,100]
输出: 1
解释:
- 计算每个整数的数位和:
[3 + 7 = 10, 1 + 0 + 0 = 1] → [10, 1]
- 根据数位和排序:
[100, 37]
。将 37
与 100
交换,得到排序后的数组。
- 因此,将
nums
排列为排序顺序所需的最小交换次数为 1。
示例 2:
输入: nums = [22,14,33,7]
输出: 0
解释:
- 计算每个整数的数位和:
[2 + 2 = 4, 1 + 4 = 5, 3 + 3 = 6, 7 = 7] → [4, 5, 6, 7]
- 根据数位和排序:
[22, 14, 33, 7]
。数组已经是排序好的。
- 因此,将
nums
排列为排序顺序所需的最小交换次数为 0。
示例 3:
输入: nums = [18,43,34,16]
输出: 2
解释:
- 计算每个整数的数位和:
[1 + 8 = 9, 4 + 3 = 7, 3 + 4 = 7, 1 + 6 = 7] → [9, 7, 7, 7]
- 根据数位和排序:
[16, 34, 43, 18]
。将 18
与 16
交换,再将 43
与 34
交换,得到排序后的数组。
- 因此,将
nums
排列为排序顺序所需的最小交换次数为 2。
提示:
1 <= nums.length <= 105
1 <= nums[i] <= 109
nums
由 互不相同 的正整数组成。
解法
方法一
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 | class Solution:
def minSwaps(self, nums: List[int]) -> int:
def f(x: int) -> int:
s = 0
while x:
s += x % 10
x //= 10
return s
n = len(nums)
arr = sorted((f(x), x) for x in nums)
d = {a[1]: i for i, a in enumerate(arr)}
ans = n
vis = [False] * n
for i in range(n):
if not vis[i]:
ans -= 1
j = i
while not vis[j]:
vis[j] = True
j = d[nums[j]]
return ans
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40 | class Solution {
public int minSwaps(int[] nums) {
int n = nums.length;
int[][] arr = new int[n][2];
for (int i = 0; i < n; i++) {
arr[i][0] = f(nums[i]);
arr[i][1] = nums[i];
}
Arrays.sort(arr, (a, b) -> {
if (a[0] != b[0]) return Integer.compare(a[0], b[0]);
return Integer.compare(a[1], b[1]);
});
Map<Integer, Integer> d = new HashMap<>();
for (int i = 0; i < n; i++) {
d.put(arr[i][1], i);
}
boolean[] vis = new boolean[n];
int ans = n;
for (int i = 0; i < n; i++) {
if (!vis[i]) {
ans--;
int j = i;
while (!vis[j]) {
vis[j] = true;
j = d.get(nums[j]);
}
}
}
return ans;
}
private int f(int x) {
int s = 0;
while (x != 0) {
s += x % 10;
x /= 10;
}
return s;
}
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33 | class Solution {
public:
int f(int x) {
int s = 0;
while (x) {
s += x % 10;
x /= 10;
}
return s;
}
int minSwaps(vector<int>& nums) {
int n = nums.size();
vector<pair<int, int>> arr(n);
for (int i = 0; i < n; ++i) arr[i] = {f(nums[i]), nums[i]};
sort(arr.begin(), arr.end());
unordered_map<int, int> d;
for (int i = 0; i < n; ++i) d[arr[i].second] = i;
vector<char> vis(n, 0);
int ans = n;
for (int i = 0; i < n; ++i) {
if (!vis[i]) {
--ans;
int j = i;
while (!vis[j]) {
vis[j] = 1;
j = d[nums[j]];
}
}
}
return ans;
}
};
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40 | func minSwaps(nums []int) int {
n := len(nums)
arr := make([][2]int, n)
for i := 0; i < n; i++ {
arr[i][0] = f(nums[i])
arr[i][1] = nums[i]
}
sort.Slice(arr, func(i, j int) bool {
if arr[i][0] != arr[j][0] {
return arr[i][0] < arr[j][0]
}
return arr[i][1] < arr[j][1]
})
d := make(map[int]int, n)
for i := 0; i < n; i++ {
d[arr[i][1]] = i
}
vis := make([]bool, n)
ans := n
for i := 0; i < n; i++ {
if !vis[i] {
ans--
j := i
for !vis[j] {
vis[j] = true
j = d[nums[j]]
}
}
}
return ans
}
func f(x int) int {
s := 0
for x != 0 {
s += x % 10
x /= 10
}
return s
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 | function f(x: number): number {
let s = 0;
while (x !== 0) {
s += x % 10;
x = Math.floor(x / 10);
}
return s;
}
function minSwaps(nums: number[]): number {
const n = nums.length;
const arr: [number, number][] = new Array(n);
for (let i = 0; i < n; i++) {
arr[i] = [f(nums[i]), nums[i]];
}
arr.sort((a, b) => (a[0] !== b[0] ? a[0] - b[0] : a[1] - b[1]));
const d = new Map<number, number>();
for (let i = 0; i < n; i++) {
d.set(arr[i][1], i);
}
const vis: boolean[] = new Array(n).fill(false);
let ans = n;
for (let i = 0; i < n; i++) {
if (!vis[i]) {
ans--;
let j = i;
while (!vis[j]) {
vis[j] = true;
j = d.get(nums[j])!;
}
}
}
return ans;
}
|