題目
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;
}
};