LeetCode 670. Maximum Swap(动态规划结合贪心)

题目

leetcode源题
给一个非负整数[0, 10^8],求至多交换一次后得到的最大值。

Example 1:
Input: 2736
Output: 7236
Explanation: Swap the number 2 and the number 7.


Example 2:
Input: 9973
Output: 9973
Explanation: No swap.

思路

时空复杂度均为O(n)

① 为了方便交换,需要记住交换的数字的数位,交换后结果 num = num - high * 10 ^ high的数位 - low * 10 ^ low的数位

② 用一个列表 bits[] 将num分割为一位位存储,对应下标 i 即为该数字对应的数位
bits[i]:代表数位 i 对应的数字

例如整数 num = 2736, 
bits[0] = 6,bits[1] = 3,bits[2] = 7,bits[2] = 2 

③ 用动态规划生成列表 dp[] 记录一些下标,用于快速寻到所交换的数字的对应数位
dp[i] :代表 num的第 [0, i - 1] 位中的最大值的数位
转移方程:
这里写图片描述

例如整数 num = 2736, 
dp[1] = 0,十位3右边最大值是个位的6,个位相应的数位是0
dp[2] = 0,百位7右边最大值是个位的6
dp[3] = 2,千位2右边最大值是百位的7,百位相应的数位是2

注意:bits[i] 存储的是数字,dp[i] 存储的是数位
使用:通过dp[i]取得数位,通过bits[dp[i]]取得该数位对应的数字,方便步骤①的计算

④ 贪心思路,尽可能把高位的数字给交换得更大
从最高位开始扫描,若出现一位数字的值小于其低位数字中的最大值,即把这两个数字交换即可得出结果

代码

class Solution {
public:
    int maximumSwap(int num) {

        // 存储每一位数字bit[0]表示最低位
        vector<int> bits;
        int tmp = num;
        while (tmp) {
            int bit = tmp % 10;
            bits.push_back(bit);
            tmp /= 10;
        }

        // dp[i]:比第i位低位中的所有数位中的最大值的下标,边界dp[0]初始化为 0
        int len = bits.size();
        vector<int> dp(len);
        for (int i = 0; i < len; i++) {
            if (i == 0) 
                dp[i] = 0;
            else if (bits[i - 1] > bits[dp[i - 1]]) 
                dp[i] = i - 1;
            else 
                dp[i] = dp[i - 1];

        }

        //从最高位往最低位扫,若第i位小于比其低位中的最大值,即num[i] < num[dp[i]],则置换这两位即可得到最大值
        int res = num;
        for (int highBit = len - 1; highBit >= 0; highBit--) {
            int lowBit = dp[highBit];
            if (bits[highBit] < bits[lowBit]) {
                //置换两位数字
                res  = num - bits[highBit] * pow(10, highBit) - bits[lowBit] * pow(10, lowBit)
                           + bits[lowBit] * pow(10, highBit) + bits[highBit] * pow(10, lowBit);

                break;
            }
        }

        return res;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值