Easy
题目描述
给你一个正整数 num。你可以交换 num 中任意两个具有相同奇偶性的数字(即都是奇数或都是偶数)。
返回经过任意次数的交换后,num 的最大可能值。
示例 1:
输入:num = 1234
输出:3412
解释:交换数字 3 和数字 1,这将得到 3214。
交换数字 2 和数字 4,这将得到 3412。
注意,也可能有其他的一些交换序列,但是可以证明 3412 是最大可能的结果。
另外请注意,我们不能交换数字 4 和数字 1,因为它们的奇偶性不同。
示例 2:
输入:num = 65875
输出:87655
解释:交换数字 8 和数字 6,这将得到 85675。
交换第一个数字 5 和数字 7,这将得到 87655。
注意,也可能有其他的一些交换序列,但是可以证明 87655 是最大可能的结果。
约束条件:
1 <= num <= 10^9
提示:
- 更大的数字应该出现在前面(更靠左),因为它对数字的值贡献更大。
- 获取所有偶数和奇数数字,分别对它们进行排序。
- 通过为较早的数字提供相同奇偶性的最高可用数字来重构数字。
解题思路
解题思路
这道题要求我们在只能交换相同奇偶性数字的条件下,得到最大的数字。
核心思路:
- 由于只能交换相同奇偶性的数字,我们可以将奇数位和偶数位分别处理
- 为了使数字最大,应该让较大的数字尽可能出现在高位
- 因此,我们可以将所有奇数数字和偶数数字分别按降序排列
- 然后按原位置的奇偶性,依次分配最大的可用数字
算法步骤:
- 将数字转换为字符串,便于操作每一位
- 遍历字符串,将奇数位和偶数位分别收集到两个数组中
- 对两个数组分别按降序排序
- 再次遍历原字符串,根据当前位置的奇偶性,从对应的排序数组中取出最大的可用数字
- 将结果转换回整数
这种方法的时间复杂度主要来自于排序操作,由于数字最多9位,所以实际复杂度很低。
推荐解法: 分离奇偶数字并排序的贪心策略。
代码实现
class Solution {
public:
int largestInteger(int num) {
string s = to_string(num);
vector<char> odds, evens;
// 收集奇数和偶数数字
for (char c : s) {
if ((c - '0') % 2 == 0) {
evens.push_back(c);
} else {
odds.push_back(c);
}
}
// 按降序排序
sort(odds.rbegin(), odds.rend());
sort(evens.rbegin(), evens.rend());
// 重构数字
int oddIndex = 0, evenIndex = 0;
for (int i = 0; i < s.length(); i++) {
if ((s[i] - '0') % 2 == 0) {
s[i] = evens[evenIndex++];
} else {
s[i] = odds[oddIndex++];
}
}
return stoi(s);
}
};
class Solution:
def largestInteger(self, num: int) -> int:
s = str(num)
odds = []
evens = []
# 收集奇数和偶数数字
for c in s:
if int(c) % 2 == 0:
evens.append(c)
else:
odds.append(c)
# 按降序排序
odds.sort(reverse=True)
evens.sort(reverse=True)
# 重构数字
result = []
odd_index = 0
even_index = 0
for c in s:
if int(c) % 2 == 0:
result.append(evens[even_index])
even_index += 1
else:
result.append(odds[odd_index])
odd_index += 1
return int(''.join(result))
public class Solution {
public int LargestInteger(int num) {
string s = num.ToString();
List<char> odds = new List<char>();
List<char> evens = new List<char>();
// 收集奇数和偶数数字
foreach (char c in s) {
if ((c - '0') % 2 == 0) {
evens.Add(c);
} else {
odds.Add(c);
}
}
// 按降序排序
odds.Sort((a, b) => b.CompareTo(a));
evens.Sort((a, b) => b.CompareTo(a));
// 重构数字
char[] result = new char[s.Length];
int oddIndex = 0, evenIndex = 0;
for (int i = 0; i < s.Length; i++) {
if ((s[i] - '0') % 2 == 0) {
result[i] = evens[evenIndex++];
} else {
result[i] = odds[oddIndex++];
}
}
return int.Parse(new string(result));
}
}
var largestInteger = function(num) {
let digits = num.toString().split('').map(Number);
let odds = [];
let evens = [];
for (let digit of digits) {
if (digit % 2 === 0) {
evens.push(digit);
} else {
odds.push(digit);
}
}
odds.sort((a, b) => b - a);
evens.sort((a, b) => b - a);
let oddIndex = 0;
let evenIndex = 0;
let result = [];
for (let digit of digits) {
if (digit % 2 === 0) {
result.push(evens[evenIndex++]);
} else {
result.push(odds[oddIndex++]);
}
}
return parseInt(result.join(''));
};
复杂度分析
| 复杂度类型 | 值 | 说明 |
|---|---|---|
| 时间复杂度 | O(d log d) | d 是数字的位数,最多9位,主要时间消耗在排序上 |
| 空间复杂度 | O(d) | 需要额外空间存储奇数和偶数数字,以及结果字符串 |
相关题目
. Sort Array By Parity (Easy)
. Sort Array By Parity II (Easy)
. Smallest String With Swaps (Medium)
. Rearrange Array Elements by Sign (Medium)