2231. Largest Number After Digit Swaps by Parity
Problem Description
You are given a positive integer num
. You can swap any two digits in the number as long as both digits have the same parity - meaning both digits must be odd (1, 3, 5, 7, 9) or both must be even (0, 2, 4, 6, 8).
For example, in the number 1234
, you could swap the 1
and 3
(both odd), or swap the 2
and 4
(both even), but you cannot swap 1
and 2
(different parity).
You can perform any number of such swaps. Your goal is to find the largest possible value of num
after performing these swaps optimally.
The key insight is that since you can only swap digits of the same parity, the positions of odd and even digits are fixed - an odd digit position will always contain an odd digit, and an even digit position will always contain an even digit. To maximize the number, you want to place the largest available digits of the appropriate parity in the leftmost positions.
Intuition
Since we can only swap digits with the same parity, each position in the number is "locked" to either odd or even digits. For instance, if position 0 has an odd digit, it will always contain an odd digit after any valid swaps.
To maximize the final number, we want to place the largest possible digit at each position, starting from the leftmost (most significant) position. The constraint is that we must use a digit with the correct parity for that position.
Think of it this way: we have two separate pools of digits - one for odd digits and one for even digits. As we build our answer from left to right, at each position we need to pick the largest available digit from the appropriate pool based on what parity that position requires.
This leads us to a greedy approach:
- Count all available digits in the original number (both odd and even)
- For each position from left to right, check what parity is needed (based on the original digit at that position)
- Pick the largest available digit with that parity
- Use that digit and decrease its count
The solution uses cnt
to track available digits and idx = [8, 9]
to track the current largest even and odd digits we're looking for. The expression x & 1
cleverly determines parity (returns 0 for even, 1 for odd). When we run out of a particular digit, we move to the next smaller digit of the same parity by decrementing by 2 (since digits of the same parity differ by 2).
Learn more about Sorting and Heap (Priority Queue) patterns.
Solution Approach
The solution uses a counting approach with a greedy strategy to build the largest possible number.
Data Structures Used:
- Convert the number to a list of digits:
nums = [int(c) for c in str(num)]
- Use
Counter
to count occurrences of each digit:cnt = Counter(nums)
- Maintain an index array
idx = [8, 9]
where:idx[0]
tracks the current largest even digit to checkidx[1]
tracks the current largest odd digit to check
Algorithm Steps:
-
Initialize tracking variables:
ans = 0
to build the result numberidx[0] = 8
(start checking from largest even digit)idx[1] = 9
(start checking from largest odd digit)
-
Process each digit position from left to right: For each digit
x
in the original number:a. Determine parity: Use
x & 1
to get:0
ifx
is even1
ifx
is odd
b. Find the largest available digit with matching parity:
while cnt[idx[x & 1]] == 0: idx[x & 1] -= 2
This loop decrements by 2 to stay within the same parity (e.g., 9→7→5→3→1 for odd, 8→6→4→2→0 for even)
c. Build the answer:
- Multiply current answer by 10 and add the selected digit:
ans = ans * 10 + idx[x & 1]
- Decrease the count of used digit:
cnt[idx[x & 1]] -= 1
-
Return the final answer
Example Walkthrough:
For num = 1234
:
- Digits:
[1, 2, 3, 4]
, counts:{1:1, 2:1, 3:1, 4:1}
- Position 0 (odd): Pick largest odd digit = 3
- Position 1 (even): Pick largest even digit = 4
- Position 2 (odd): Pick remaining odd digit = 1
- Position 3 (even): Pick remaining even digit = 2
- Result:
3412
The time complexity is O(n)
where n
is the number of digits, and space complexity is O(1)
since we only store counts for at most 10 digits.
Ready to land your dream job?
Unlock your dream job with a 3-minute evaluator for a personalized learning plan!
Start EvaluatorExample Walkthrough
Let's walk through the solution with num = 52841
:
Step 1: Initialize
- Convert to digits:
nums = [5, 2, 8, 4, 1]
- Count occurrences:
cnt = {5:1, 2:1, 8:1, 4:1, 1:1}
- Set
idx = [8, 9]
(largest even and odd digits to check) ans = 0
Step 2: Process each position
Position 0 (digit 5, odd):
- Parity check:
5 & 1 = 1
(odd) - Look for largest odd digit:
idx[1] = 9
- Check
cnt[9] = 0
, so decrement:idx[1] = 7
- Check
cnt[7] = 0
, so decrement:idx[1] = 5
- Check
cnt[5] = 1
✓ Found! - Use digit 5:
ans = 0 * 10 + 5 = 5
- Update:
cnt[5] = 0
Position 1 (digit 2, even):
- Parity check:
2 & 1 = 0
(even) - Look for largest even digit:
idx[0] = 8
- Check
cnt[8] = 1
✓ Found! - Use digit 8:
ans = 5 * 10 + 8 = 58
- Update:
cnt[8] = 0
Position 2 (digit 8, even):
- Parity check:
8 & 1 = 0
(even) - Current
idx[0] = 8
, butcnt[8] = 0
- Decrement:
idx[0] = 6
, checkcnt[6] = 0
- Decrement:
idx[0] = 4
, checkcnt[4] = 1
✓ Found! - Use digit 4:
ans = 58 * 10 + 4 = 584
- Update:
cnt[4] = 0
Position 3 (digit 4, even):
- Parity check:
4 & 1 = 0
(even) - Current
idx[0] = 4
, butcnt[4] = 0
- Decrement:
idx[0] = 2
, checkcnt[2] = 1
✓ Found! - Use digit 2:
ans = 584 * 10 + 2 = 5842
- Update:
cnt[2] = 0
Position 4 (digit 1, odd):
- Parity check:
1 & 1 = 1
(odd) - Current
idx[1] = 5
, butcnt[5] = 0
- Decrement:
idx[1] = 3
, checkcnt[3] = 0
- Decrement:
idx[1] = 1
, checkcnt[1] = 1
✓ Found! - Use digit 1:
ans = 5842 * 10 + 1 = 58421
- Update:
cnt[1] = 0
Result: 58421
Notice how odd positions (0, 4) kept odd digits (5, 1) and even positions (1, 2, 3) kept even digits (8, 4, 2), but we rearranged them optimally within their parity groups to maximize the number.
Solution Implementation
1from collections import Counter
2
3class Solution:
4 def largestInteger(self, num: int) -> int:
5 # Convert the number to a list of individual digits
6 digits = [int(char) for char in str(num)]
7
8 # Count the frequency of each digit
9 digit_count = Counter(digits)
10
11 # Initialize pointers for the largest available even (8) and odd (9) digits
12 # Index 0 for even digits, index 1 for odd digits
13 largest_available = [8, 9]
14
15 # Build the result number
16 result = 0
17
18 for digit in digits:
19 # Determine if current digit is even (0) or odd (1) using bitwise AND
20 parity = digit & 1
21
22 # Find the largest available digit with the same parity
23 while digit_count[largest_available[parity]] == 0:
24 # Move to the next smaller digit with same parity (decrease by 2)
25 largest_available[parity] -= 2
26
27 # Add the largest available digit with matching parity to result
28 result = result * 10 + largest_available[parity]
29
30 # Decrease the count of the used digit
31 digit_count[largest_available[parity]] -= 1
32
33 return result
34
1class Solution {
2 public int largestInteger(int num) {
3 // Convert the number to a character array for digit-by-digit processing
4 char[] digits = String.valueOf(num).toCharArray();
5
6 // Count frequency of each digit (0-9) in the original number
7 int[] digitFrequency = new int[10];
8 for (char digit : digits) {
9 digitFrequency[digit - '0']++;
10 }
11
12 // Initialize pointers for the largest available even and odd digits
13 // evenPointer starts at 8 (largest even digit), oddPointer starts at 9 (largest odd digit)
14 int[] largestAvailable = {8, 9}; // index 0 for even, index 1 for odd
15
16 // Build the result number
17 int result = 0;
18 for (char digit : digits) {
19 int currentDigit = digit - '0';
20 // Determine parity: 0 for even, 1 for odd (using bitwise AND with 1)
21 int parity = currentDigit & 1;
22
23 // Find the next largest available digit with the same parity
24 // Move pointer down by 2 to maintain parity (8->6->4->2->0 or 9->7->5->3->1)
25 while (digitFrequency[largestAvailable[parity]] == 0) {
26 largestAvailable[parity] -= 2;
27 }
28
29 // Append the largest available digit with matching parity to result
30 result = result * 10 + largestAvailable[parity];
31
32 // Decrement the frequency of the used digit
33 digitFrequency[largestAvailable[parity]]--;
34 }
35
36 return result;
37 }
38}
39
1class Solution {
2public:
3 int largestInteger(int num) {
4 // Convert number to string for digit-by-digit processing
5 string numStr = to_string(num);
6
7 // Count frequency of each digit (0-9)
8 int digitFrequency[10] = {0};
9 for (char digitChar : numStr) {
10 digitFrequency[digitChar - '0']++;
11 }
12
13 // Pointers to track largest available even and odd digits
14 // evenPointer starts at 8 (largest even digit)
15 // oddPointer starts at 9 (largest odd digit)
16 int largestAvailable[2] = {8, 9}; // [0] for even, [1] for odd
17
18 int result = 0;
19
20 // Process each digit position in the original number
21 for (char digitChar : numStr) {
22 int currentDigit = digitChar - '0';
23
24 // Determine parity: 0 for even, 1 for odd
25 int parity = currentDigit & 1;
26
27 // Find the largest available digit with same parity
28 while (digitFrequency[largestAvailable[parity]] == 0) {
29 largestAvailable[parity] -= 2; // Move to next smaller digit of same parity
30 }
31
32 // Use the largest available digit with matching parity
33 result = result * 10 + largestAvailable[parity];
34
35 // Decrease the count of used digit
36 digitFrequency[largestAvailable[parity]]--;
37 }
38
39 return result;
40 }
41};
42
1/**
2 * Rearranges digits of a number to form the largest possible integer
3 * while maintaining the parity (odd/even) of each digit's position
4 * @param num - The input number to rearrange
5 * @returns The largest integer possible with the same parity constraints
6 */
7function largestInteger(num: number): number {
8 // Convert number to array of digit characters
9 const digitChars: string[] = num.toString().split('');
10
11 // Count frequency of each digit (0-9)
12 const digitFrequency: number[] = Array(10).fill(0);
13
14 // Count occurrences of each digit in the input number
15 for (const digitChar of digitChars) {
16 const digit: number = Number(digitChar);
17 digitFrequency[digit]++;
18 }
19
20 // Pointers to track the largest available even and odd digits
21 // Index 0: pointer for even digits (starts at 8)
22 // Index 1: pointer for odd digits (starts at 9)
23 const largestAvailableDigit: number[] = [8, 9];
24
25 // Build the result number
26 let result: number = 0;
27
28 // Process each digit position in the original number
29 for (const digitChar of digitChars) {
30 const currentDigit: number = Number(digitChar);
31 const parityIndex: number = currentDigit % 2; // 0 for even, 1 for odd
32
33 // Find the largest available digit with the same parity
34 while (digitFrequency[largestAvailableDigit[parityIndex]] === 0) {
35 largestAvailableDigit[parityIndex] -= 2; // Move to next smaller digit with same parity
36 }
37
38 // Append the largest available digit to result
39 result = result * 10 + largestAvailableDigit[parityIndex];
40
41 // Decrease the frequency of the used digit
42 digitFrequency[largestAvailableDigit[parityIndex]]--;
43 }
44
45 return result;
46}
47
Time and Space Complexity
The time complexity is O(log num)
, where num
is the input integer. This is because:
- Converting the integer to a string takes
O(log num)
time (the number of digits innum
is proportional tolog num
) - Creating the list of digits takes
O(log num)
time - Building the Counter takes
O(log num)
time since there are at mostO(log num)
digits - The main loop iterates through each digit once, which is
O(log num)
iterations - Inside the loop, the while loop can decrement
idx[x & 1]
at most 5 times (for even digits: 8, 6, 4, 2, 0; for odd digits: 9, 7, 5, 3, 1), making itO(1)
per iteration - Therefore, the overall time complexity is
O(log num)
The space complexity is O(log num)
because:
- The
nums
list stores all digits of the input number, requiringO(log num)
space - The Counter dictionary stores at most 10 unique digits (0-9), which is
O(1)
, but containsO(log num)
total counts - The
idx
array usesO(1)
space - The total space complexity is dominated by the storage of digits, resulting in
O(log num)
Learn more about how to find time and space complexity quickly.
Common Pitfalls
Pitfall 1: Not Preserving Position-Based Parity Constraint
The Problem:
A common mistake is to simply sort all odd and even digits separately and try to arrange them in descending order without respecting the original positions. For example, with num = 2143
, you might incorrectly think you can rearrange it as 4321
by sorting all digits in descending order.
Why It's Wrong: The problem requires that each position maintains its original parity type. If position 0 had an even digit originally, it must contain an even digit in the final result. If position 1 had an odd digit, it must contain an odd digit in the final result.
Correct Understanding:
- For
2143
: positions are [even, odd, even, odd] - You can only place even digits in positions 0 and 2
- You can only place odd digits in positions 1 and 3
- Correct answer:
4321
(4 and 2 in even positions, 3 and 1 in odd positions)
Pitfall 2: Incorrect Parity Tracking with Index Decrementation
The Problem: When searching for the next available digit of the same parity, developers might incorrectly decrement by 1 instead of 2:
# WRONG - This would check digits of wrong parity while digit_count[largest_available[parity]] == 0: largest_available[parity] -= 1 # Should be -= 2
Why It's Wrong: Decrementing by 1 would alternate between even and odd digits. For example, starting from 9 (odd), you'd check 8 (even), 7 (odd), etc., mixing parities.
Correct Approach: Always decrement by 2 to stay within the same parity:
- Odd sequence: 9 → 7 → 5 → 3 → 1
- Even sequence: 8 → 6 → 4 → 2 → 0
Pitfall 3: Edge Case with Leading Zeros
The Problem: If the input number starts with small even digits and has zeros, there's a theoretical concern about whether zeros could end up in the leading position.
Why It's Not Actually a Problem (but worth understanding): The problem states we're given a "positive integer", which by definition cannot start with 0. Additionally, our algorithm preserves positional parity, so if the original number didn't start with 0, the result won't either.
Example:
For num = 2001
:
- Positions: [even, even, even, odd]
- Available even digits: 2, 0, 0
- Available odd digit: 1
- Result:
2001
(the 2 naturally stays in front as it's the largest even digit)
Solution to Avoid These Pitfalls:
def largestInteger(self, num: int) -> int:
digits = [int(c) for c in str(num)]
# Separate digits by parity while preserving which positions need which parity
odd_digits = sorted([d for d in digits if d % 2 == 1], reverse=True)
even_digits = sorted([d for d in digits if d % 2 == 0], reverse=True)
# Use iterators to track which digit to use next
odd_iter = iter(odd_digits)
even_iter = iter(even_digits)
# Build result maintaining position-based parity
result = []
for original_digit in digits:
if original_digit % 2 == 1:
result.append(next(odd_iter))
else:
result.append(next(even_iter))
return int(''.join(map(str, result)))
This alternative approach explicitly separates the sorting logic from the position-preservation logic, making the constraint clearer and reducing the chance of errors.
Which of the two traversal algorithms (BFS and DFS) can be used to find whether two nodes are connected?
Recommended Readings
Sorting Summary Comparisons We presented quite a few sorting algorithms and it is essential to know the advantages and disadvantages of each one The basic algorithms are easy to visualize and easy to learn for beginner programmers because of their simplicity As such they will suffice if you don't know any advanced
https assets algo monster cover_photos heap svg Priority Queue and Heap What is the relationship between priority queue and heap Priority Queue is an Abstract Data Type and Heap is the concrete data structure we use to implement a priority queue Priority Queue A priority queue is a data structure
Coding Interview Patterns Your Personal Dijkstra's Algorithm to Landing Your Dream Job The goal of AlgoMonster is to help you get a job in the shortest amount of time possible in a data driven way We compiled datasets of tech interview problems and broke them down by patterns This way
Want a Structured Path to Master System Design Too? Don’t Miss This!