670. Maximum Swap**

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);
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值