Skip to content

Commit 0807d86

Browse files
committed
feat(algorithms, greedy): maximum swap
1 parent aff77c8 commit 0807d86

14 files changed

Lines changed: 503 additions & 4 deletions

algorithms/greedy/maximum_swap/README.md

Lines changed: 354 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
from typing import List
2+
3+
4+
def maximum_swap(num: int) -> int:
5+
# Convert the number to a list of characters for easy manipulation
6+
digits: List[str] = list(str(num))
7+
n = len(digits)
8+
9+
# Variables to track the index of the maximum digit and the two swap indices
10+
max_digit_index = index_1 = index_2 = -1
11+
12+
# Iterate the string from the last digit to the first
13+
for i in range(n - 1, -1, -1):
14+
# Update the max digit index if the current digit is greater
15+
if max_digit_index == -1 or digits[i] > digits[max_digit_index]:
16+
max_digit_index = i
17+
# If the current digit is less than the max digit found so far,
18+
# mark this index (index_1) and the max digit's index (index_2) for swapping
19+
elif digits[i] < digits[max_digit_index]:
20+
index_1 = i
21+
index_2 = max_digit_index
22+
23+
# Perform the swap if valid indices are found
24+
if index_1 != -1 and index_2 != -1:
25+
digits[index_1], digits[index_2] = digits[index_2], digits[index_1]
26+
27+
# Convert the list back to an integer and return it
28+
return int("".join(digits))
29+
30+
31+
def maximum_swap_suboptimal_greedy(num: int) -> int:
32+
num_str = str(num)
33+
n = len(num_str)
34+
last_seen = [-1] * 10 # Store the last occurrence of each digit
35+
36+
# Record the last occurrence of each digit
37+
for i in range(n):
38+
last_seen[int(num_str[i])] = i
39+
40+
# Traverse the string to find the first digit that can be swapped with a larger one
41+
for i in range(n):
42+
for d in range(9, int(num_str[i]), -1):
43+
if last_seen[d] > i:
44+
# Perform the swap
45+
num_str = list(num_str)
46+
num_str[i], num_str[last_seen[d]] = (
47+
num_str[last_seen[d]],
48+
num_str[i],
49+
)
50+
num_str = "".join(num_str)
51+
52+
return int(num_str) # Return the new number immediately after the swap
53+
54+
return num # Return the original number if no swap can maximize it
55+
56+
57+
def maximum_swap_greedy_two_pass(num: int) -> int:
58+
num_str = list(str(num))
59+
n = len(num_str)
60+
max_right_index = [0] * n
61+
62+
max_right_index[n - 1] = n - 1
63+
for i in range(n - 2, -1, -1):
64+
max_right_index[i] = (
65+
i
66+
if num_str[i] > num_str[max_right_index[i + 1]]
67+
else max_right_index[i + 1]
68+
)
69+
70+
for i in range(n):
71+
if num_str[i] < num_str[max_right_index[i]]:
72+
num_str[i], num_str[max_right_index[i]] = (
73+
num_str[max_right_index[i]],
74+
num_str[i],
75+
)
76+
return int("".join(num_str))
77+
78+
return num
79+
80+
81+
def maximum_swap_brute_force(num: int) -> int:
82+
num_str = str(num) # Convert num to string for easy manipulation
83+
n = len(num_str)
84+
max_num = num # Track the maximum number found
85+
86+
# Try all possible swaps
87+
for i in range(n):
88+
for j in range(i + 1, n):
89+
num_list = list(num_str) # Convert the string to list for swapping
90+
91+
num_list[i], num_list[j] = (
92+
num_list[j],
93+
num_list[i],
94+
) # Swap digits at index i and j
95+
temp = int(
96+
"".join(num_list)
97+
) # Convert the list back to string and then to integer
98+
99+
max_num = max(max_num, temp) # Update max_num if the new number is larger
100+
101+
return max_num # Return the largest number after all possible swaps
25.6 KB
Loading
21.7 KB
Loading
27.8 KB
Loading
27 KB
Loading
30.4 KB
Loading
30.1 KB
Loading
29.3 KB
Loading
23.7 KB
Loading

0 commit comments

Comments
 (0)