670. Maximum Swap**
https://leetcode.com/problems/maximum-swap/
题目描述
Given a non-negative integer, you could swap two digits at most once to get the maximum valued number. Return the maximum valued number you could get.
Example 1:
Input: 2736
Output: 7236
Explanation: Swap the number 2 and the number 7.
Example 2:
Input: 9973
Output: 9973
Explanation: No swap.
Note:
The given number is in the range
[
0
,
1
0
8
]
[0, 10^8]
[0,108]
C++ 实现 1
贪婪策略. 来自 LeetCode 的解答: https://leetcode.com/problems/maximum-swap/solution/
发现英文的表述更为精准, 这里引用一下:
Intuition
At each digit of the input number in order, if there is a larger digit that occurs later, we know that the best swap must occur with the digit we are currently considering.
Algorithm
We will compute last[d] = i \text{last[d] = i} last[d] = i the index i \text{i} i of the last occurrence of digit d \text{d} d (if it exists).
Afterwards, when scanning the number from left to right, if there is a larger digit in the future, we will swap it with the largest such digit; if there are multiple such digits, we will swap it with the one that occurs the latest.
概括来说, 依次访问 num
中的每个数字, 比如访问到 digits[i]
时, 如果后面还出现了更大的数字 k
, 那么用 k
来和 digits[i]
交换, 就能获取最大的结果. 为此, 从 [9, digits[i])
范围内搜索 k
.
下面代码中, 在 pos
保存每个数字的索引, 需要注意的是, 如果 num
存在相同的元素, 保存的是最远的元素的索引, 这样可以保证交换
d
i
g
i
t
s
[
i
]
digits[i]
digits[i] 和
k
k
k 时, 最后获得结果最大. 比如 1993
, 要用第二个 9
来和 1
交换.
class Solution {
public:
int maximumSwap(int num) {
vector<int> pos(10, 0);
string digits = std::to_string(num);
// 如果有相同的数字, 那么保存最远的那个
for (int i = 0; i < digits.size(); ++ i)
pos[digits[i] - '0'] = i;
// 对每个位置上的数字 digits[i], 从 k = 9 开始搜索, 判断
// digits[i] 之后是否存在大于 digits[i] 的数字.
for (int i = 0; i < digits.size(); ++ i) {
int n = digits[i] - '0';
for (int k = 9; k > n; --k) {
if (pos[k] > i) { // pos[k] > i 保证满足条件的数字出现在 digits[i] 之后
std::swap(digits[i], digits[pos[k]]);
return std::stoi(digits);
}
}
}
return std::stoi(digits);
}
};