題目地址:
https://leetcode.com/problems/maximum-swap/
給定一個十進制正整數,允許調換其中兩個位置的值(也可以選擇不調換),問能得到的最大整數是多少。
先將的各個位上的數字取出,形成的數組不妨仍然叫,然後將其從大到小排序,得新數組,可以證明,第一個使得的情形,這兩個數就是需要調換的兩個數。當然如果不存在這樣的兩個數,就不需要對換。接着從的最低位開始找這個數,最後將其與調換即可。代碼如下:
import java.util.Arrays;
public class Solution {
public int maximumSwap(int num) {
if (num < 10) {
return num;
}
char[] n = String.valueOf(num).toCharArray();
char[] tmp = Arrays.copyOf(n, n.length);
// 從大到小排序
Arrays.sort(tmp);
flip(tmp);
// 找第一個不等的地方
int j = -1, swap = -1;
for (int i = 0; i < n.length; i++) {
// 找到了之後記錄一下是n的哪個位置,並記錄這個位置需要和哪個數對換;
// 一旦找到就退出循環
if (n[i] != tmp[i]) {
j = i;
swap = tmp[i];
break;
}
}
// 如果沒找到,說明原數就是最大的,返回之
if (j == -1) {
return num;
}
// 從後向前找t[i],找到了就與n[i]對換,並退出循環
for (int i = n.length - 1; i >= 0; i--) {
if (n[i] == swap) {
swap(n, i, j);
break;
}
}
// 返回n代表的十進制數
return Integer.parseInt(new String(n));
}
private void flip(char[] chs) {
int i = 0, j = chs.length - 1;
while (i < j) {
swap(chs, i, j);
i++;
j--;
}
}
private void swap(char[] chs, int i, int j) {
char tmp = chs[i];
chs[i] = chs[j];
chs[j] = tmp;
}
}
時空複雜度。
算法正確性證明:
首先如果的是單調下降的,那麼就不用調換了,因爲一旦調換就有可能將高位換成一個較小的數字,一定會得到更小的數。否則將從大到小排序得到新的數組,接着從高位到低位比較與的每一位,直到第一次發現了,那麼說明,我們取最大的符合這個條件的,接下來我們證明調換的和位就能得到最大的數。首先一定要與這個數調換,否則的話就得用一個較小的數放在這個位置,得到的數字一定較小。其次,一定要取最大的符合條件的,如果不取最大的話,調換之後得到的數的第位就會比那個“最優解”小,所以不行。證畢。