【Leetcode】670. Maximum Swap

題目地址:

https://leetcode.com/problems/maximum-swap/

給定一個十進制正整數nn,允許調換其中兩個位置的值(也可以選擇不調換),問能得到的最大整數是多少。

先將nn的各個位上的數字取出,形成的數組不妨仍然叫nn,然後將其從大到小排序,得新數組tt,可以證明,第一個ii使得n[i]t[i]n[i] \ne t[i]的情形,這兩個數就是需要調換的兩個數。當然如果不存在這樣的兩個數,就不需要對換。接着從nn的最低位開始找t[i]t[i]這個數,最後將其與n[i]n[i]調換即可。代碼如下:

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

時空複雜度O(logn)O(\log n)

算法正確性證明:
首先如果nn的是單調下降的,那麼就不用調換了,因爲一旦調換就有可能將高位換成一個較小的數字,一定會得到更小的數。否則將nn從大到小排序得到新的數組tt,接着從高位到低位比較nntt的每一位,直到第一次發現了n[i]t[i]n[i]\ne t[i],那麼說明j>i,n[j]=t[i]\exists j>i,n[j]=t[i],我們取最大的符合這個條件的jj,接下來我們證明調換nniijj位就能得到最大的數。首先n[i]n[i]一定要與n[j]n[j]這個數調換,否則的話就得用一個較小的數放在ii這個位置,得到的數字一定較小。其次,一定要取最大的符合條件的jj,如果不取最大的話,調換之後得到的數的第jj位就會比那個“最優解”小,所以不行。證畢。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章