Maximum Swap
Swap at most two digits once to make a number as large as possible — last-occurrence lookup.
3 min read
greedy string
Problem#
Swap any two digits at most once to maximize the resulting integer.
Examples#
2736→72369973→9973
Constraints#
0 <= num <= 10^8.
Approach#
Record last[d] = last index of each digit. Walk left-to-right; for each position, look for any larger digit d (9 down to current+1) whose last occurrence is to the right — swap and return.
Solution#
class Solution {public: int maximumSwap(int num) { string s = to_string(num); int last[10] = {0}; for (int i = 0; i < (int)s.size(); ++i) last[s[i] - '0'] = i; for (int i = 0; i < (int)s.size(); ++i) { for (int d = 9; d > s[i] - '0'; --d) { if (last[d] > i) { swap(s[i], s[last[d]]); return stoi(s); } } } return num; }};import "strconv"
func maximumSwap(num int) int { s := []byte(strconv.Itoa(num)) var last [10]int for i := 0; i < len(s); i++ { last[s[i]-'0'] = i } for i := 0; i < len(s); i++ { for d := 9; d > int(s[i]-'0'); d-- { if last[d] > i { s[i], s[last[d]] = s[last[d]], s[i] v, _ := strconv.Atoi(string(s)) return v } } } return num}class Solution: def maximumSwap(self, num: int) -> int: s = list(str(num)) last = {int(d): i for i, d in enumerate(s)} for i, ch in enumerate(s): cur = int(ch) for d in range(9, cur, -1): if last.get(d, -1) > i: s[i], s[last[d]] = s[last[d]], s[i] return int(''.join(s)) return numfunction maximumSwap(num) { const s = String(num).split(''); const last = new Array(10).fill(0); for (let i = 0; i < s.length; i++) last[+s[i]] = i; for (let i = 0; i < s.length; i++) { const cur = +s[i]; for (let d = 9; d > cur; d--) { if (last[d] > i) { [s[i], s[last[d]]] = [s[last[d]], s[i]]; return parseInt(s.join(''), 10); } } } return num;}class Solution { public int maximumSwap(int num) { char[] s = Integer.toString(num).toCharArray(); int[] last = new int[10]; for (int i = 0; i < s.length; i++) last[s[i] - '0'] = i; for (int i = 0; i < s.length; i++) { for (int d = 9; d > s[i] - '0'; d--) { if (last[d] > i) { char tmp = s[i]; s[i] = s[last[d]]; s[last[d]] = tmp; return Integer.parseInt(new String(s)); } } } return num; }}function maximumSwap(num: number): number { const s: string[] = String(num).split(''); const last: number[] = new Array(10).fill(0); for (let i = 0; i < s.length; i++) last[+s[i]] = i; for (let i = 0; i < s.length; i++) { const cur = +s[i]; for (let d = 9; d > cur; d--) { if (last[d] > i) { [s[i], s[last[d]]] = [s[last[d]], s[i]]; return parseInt(s.join(''), 10); } } } return num;}Editorial#
For each position left-to-right, the greedy ideal is to swap in the largest digit available later in the string. The “later” requirement is what makes this a swap (not a re-arrangement). Walking digits 9 down to current+1 finds the largest improvement at the leftmost position — the highest-impact swap.
Complexity#
- Time: O(n × 10) = O(n).
- Space: O(1).
Concept revision#
Related#