670.最大交换

输入一个非负整数,至多可以交换一次数字中的任意两位。
返回你能得到的最大值。

将数字拆分,每一位放进数组num[i]。将最高位换成最大的数,如果最高位是最大的,将次高位换成第二大的数…

直接遍历

由于对于整数 num的十进制数字位长最长为 888 位,任意两个数字交换一次最多有 282828 种不同的交换方法,因此我们可以尝试遍历所有可能的数字交换方法即可,并找到交换后的最大数字即可。

我们将数字存储为长度为 n 的列表,其中 n 为整数 num的十进制位数的长度。对于位置为 (i, j)的每个候选交换,我们交换数字并记录组成的新数字是否大于当前答案;
对于前导零的问题,我们也不需要特殊处理。
由于数字只有 8 位,所以我们不必考虑交换后溢出的风险

C

#define MAX(a, b) ((a) > (b) ? (a) : (b))
#define MAX_LEN 32

static inline void swap(char* a, char* b) {
    char c = *a;
    *a = *b;
    *b = c;
}

int maximumSwap(int num) {
    char charArray[MAX_LEN];
    sprintf(charArray, "%d", num);
    int n = strlen(charArray);
    int maxNum = num;
    for (int i = 0; i < n; i++) {
        for (int j = i + 1; j < n; j++) {
            swap(&charArray[i], &charArray[j]);
            maxNum = MAX(maxNum, atoi(charArray));
            swap(&charArray[i], &charArray[j]);
        }
    }
    return maxNum;
}

python

class Solution:
    def maximumSwap(self, num: int) -> int:
        ans = num
        s = list(str(num))
        for i in range(len(s)):
            for j in range(i):
                s[i], s[j] = s[j], s[i]
                ans = max(ans, int(''.join(s)))
                s[i], s[j] = s[j], s[i]
        return ans

贪心

设整数 num 从右向左的数字分别为 (d0,d1,d2,⋯ ,dn−1),则此时我们可以知道: num=∑i=0n−1di×10^i ,假设我们对位于j,k位上的数字进行交换,其中满足 0≤j

val=∑i=0n−1(di×10i)+(dj−dk)×10k−(dj−dk)×10j=∑i=0n−1(di×10i)+(dj−dk)×(10k−10j)
根据以上等式我们可以看出,若使得 val的值最大,应依次满足如下条件:

最优的交换一定需要满足 dj>dk;
在满足 dj>dk时,应该保证索引 k 越大从而使得数字 val越大;
在同样大小的数字 dk时,应使得数字 dj越大从而使得 val越大;
在同样大小的数字 dj时,应使得索引 j越小从而使得 val越大;
通过以上可以观察到右边越大的数字与左边较小的数字进行交换,这样产生的整数才能保证越大。因此我们可以利用贪心法则,尝试将数字中右边较大的数字与左边较小的数字进行交换,这样即可保证得到的整数值最大。具体做法如下:

我们将从右向左扫描数字数组,并记录当前已经扫描过的数字的最大值的索引为 maxId\textit{maxId}maxId 且保证 maxId\textit{maxId}maxId 越靠近数字的右侧,此时则说明 charArray[maxId]\textit{charArray}[\textit{maxId}]charArray[maxId] 则为当前已经扫描过的最大值。
如果检测到当前数字 charArray[i]

C

#define MAX_LEN 32

static inline void swap(char* a, char* b) {
    char c = *a;
    *a = *b;
    *b = c;
}

int maximumSwap(int num) {
    char charArray[MAX_LEN];
    sprintf(charArray, "%d", num);
    int n = strlen(charArray);
    char maxIdx = n - 1;
    int idx1 = -1, idx2 = -1;
    for (int i = n - 1; i >= 0; i--) {
        if (charArray[i] > charArray[maxIdx]) {
            maxIdx = i;
        } else if (charArray[i] < charArray[maxIdx]) {
            idx1 = i;
            idx2 = maxIdx;
        }
    }
    if (idx1 >= 0) {
        swap(&charArray[idx1], &charArray[idx2]);
        return atoi(charArray);
    } else {
        return num;
    }
}

python

class Solution:
    def maximumSwap(self, num: int) -> int:
        s = list(str(num))
        n = len(s)
        maxIdx = n - 1
        idx1 = idx2 = -1
        for i in range(n - 1, -1, -1):
            if s[i] > s[maxIdx]:
                maxIdx = i
            elif s[i] < s[maxIdx]:
                idx1, idx2 = i, maxIdx
        if idx1 < 0:
            return num
        s[idx1], s[idx2] = s[idx2], s[idx1]
        return int(''.join(s))


你可能感兴趣的:(算法,数据结构)