LC 670. 最大交换

题目描述

这是 LeetCode 上的 670. 最大交换 ,难度为 中等

给定一个非负整数,你至多可以交换一次数字中的任意两位。

返回你能得到的最大值。

示例 1 :

1
2
3
4
5
输入: 2736

输出: 7236

解释: 交换数字2和数字7。

示例 2 :
1
2
3
4
5
输入: 9973

输出: 9973

解释: 不需要交换。

注意:

  • 给定数字的范围是 $[0, 10^8]$

模拟

根据题意,我们应当将大的数放置在高位,而当有数值相同的多个大数时,我们应当选择低位的数字。

因此,我们可以先将 num 的每一位处理出来存放到数组 list 中,随后预处理一个与 list 等长的数组 idx,带来代指 num 后缀中最大值对应的下标,即当 idx[i] = j 含义为在下标为 $[0, i]$ 位中 $num[j]$ 对应的数值最大。

同时由于我们需要遵循「当有数值相同的多个大数时,选择低位的数字」原则,我们应当出现采取严格大于才更新的方式来预处理 idx

最后则是从高位往低位遍历,找到第一个替换的位置进行交换,并重新拼凑回答案。

Java 代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class Solution {
public int maximumSwap(int num) {
List<Integer> list = new ArrayList<>();
while (num != 0) {
list.add(num % 10); num /= 10;
}
int n = list.size(), ans = 0;
int[] idx = new int[n];
for (int i = 0, j = 0; i < n; i++) {
if (list.get(i) > list.get(j)) j = i;
idx[i] = j;
}
for (int i = n - 1; i >= 0; i--) {
if (list.get(idx[i]) != list.get(i)) {
int c = list.get(idx[i]);
list.set(idx[i], list.get(i));
list.set(i, c);
break;
}
}
for (int i = n - 1; i >= 0; i--) ans = ans * 10 + list.get(i);
return ans;
}
}

C++ 代码:
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
class Solution {
public:
int maximumSwap(int num) {
vector<int> list;
while (num != 0) {
list.push_back(num % 10); num /= 10;
}
int n = list.size(), ans = 0;
int* idx = new int[n];
for (int i = 0, j = 0; i < n; i++) {
if (list[i] > list[j]) j = i;
idx[i] = j;
}
for (int i = n - 1; i >= 0; i--) {
if (list[idx[i]] != list[i]) {
int c = list[idx[i]];
list[idx[i]] = list[i];
list[i] = c;
break;
}
}
for (int i = n - 1; i >= 0; i--) ans = ans * 10 + list[i];
return ans;
}
};

Python 代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class Solution:
def maximumSwap(self, num: int) -> int:
nums = []
while num != 0:
nums.append(num % 10); num //= 10
n, ans = len(nums), 0
idx = [0] * n
i, j = 0, 0
while i < n:
if nums[i] > nums[j]: j = i
idx[i] = j
i += 1
for i in range(n - 1, -1, -1):
if nums[idx[i]] != nums[i]:
c = nums[idx[i]]
nums[idx[i]] = nums[i]
nums[i] = c
break
for i in range(n - 1, -1, -1):
ans = ans * 10 + nums[i]
return ans

TypeScript 代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
function maximumSwap(num: number): number {
const list = new Array<number>()
while (num != 0) {
list.push(num % 10)
num = Math.floor(num / 10)
}
let n = list.length, ans = 0
const idx = new Array<number>()
for (let i = 0, j = 0; i < n; i++) {
if (list[i] > list[j]) j = i
idx.push(j)
}
for (let i = n - 1; i >= 0; i--) {
if (list[idx[i]] != list[i]) {
const c = list[idx[i]]
list[idx[i]] = list[i]
list[i] = c
break
}
}
for (let i = n - 1; i >= 0; i--) ans = ans * 10 + list[i];
return ans
};

  • 时间复杂度:$O(\log{num})$
  • 空间复杂度:$O(\log{num})$

最后

这是我们「刷穿 LeetCode」系列文章的第 No.670 篇,系列开始于 2021/01/01,截止于起始日 LeetCode 上共有 1916 道题目,部分是有锁题,我们将先把所有不带锁的题目刷完。

在这个系列文章里面,除了讲解解题思路以外,还会尽可能给出最为简洁的代码。如果涉及通解还会相应的代码模板。

为了方便各位同学能够电脑上进行调试和提交代码,我建立了相关的仓库:https://github.com/SharingSource/LogicStack-LeetCode

在仓库地址里,你可以看到系列文章的题解链接、系列文章的相应代码、LeetCode 原题链接和其他优选题解。


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!