The most straightforward approach is to generate every possible permutation of the digits, sort them, and then find the smallest even permutation that is greater than the original number. While this method is simple to understand, it is extremely inefficient due to the exponential number of permutations involved.
We can improve on this by analyzing the problem more closely and developing an algorithm that avoids generating all permutations. Before that, let’s first consider how to find the next permutation in lexicographical order.
⏰ Time complexity: O(n!) — Generating all permutations of n digits is factorial in time.
🧺 Space complexity: O(n!) — Storing all permutations also requires factorial space.
Let’s first revisit how to find the next permutation, and then see how to adapt it for the next even permutation. For a full explanation, see Next permutation of a number.
To find the next permutation, start from the right and look for the first digit that is smaller than the digit immediately after it. For example, with the number 12344875, the first such digit from the right is 4.
Next, scan to the right of this digit to find the smallest digit that is larger than 4—in this case, it’s 5 in the sequence 875. Swap these two digits, resulting in 12345874.
After swapping, sort all digits to the right of the swapped position in ascending order. This gives 12345784, which is the next permutation in lexicographical order. However, this process does not guarantee the result is even.
To ensure the next permutation is even, you need to adjust the process. If the last digit after swapping and sorting is even, you’re done. If not, you need to permute the digits to get an even number at the end.
For example, if the last digit is not even, look for the rightmost even digit that can be swapped to the end, and rearrange the remaining digits to get the smallest possible even permutation greater than the original.
If there is no such even digit, or the number is already the largest permutation, then no valid next even permutation exists.
Suppose your number is 123475531. Start from the right and look for the first even digit that has a larger digit to its right. Swap 4 with the smallest digit greater than 4 to its right, resulting in 123575431. Move the even digit (4) to the end and sort the digits between the swapped positions in ascending order, giving 123513574.
For another example, consider 136531. If there is no even digit with a greater digit to its right, look at the next digit to the left and repeat the process. Swap and move the even digit to the end, then sort the remaining digits. This sequence could go: 136531 → 156331 → 153316 → 151336.
If the number is in descending order, such as 97654, or if there is only one even digit with no higher digit to its right, and no digits to the left have a greater digit to their right (e.g., 976173), then no solution exists.
Let’s use N = 8234961 as an example and follow the process with added checks for even digits:
Identify the longest non-decreasing sequence from the right and split the number into X and Y. Track whether Y contains an even digit.
For N = 8234 | 961, X = 8234, Y = 961, a = 4, and evenExist = true.
If Y does not contain an even digit, extend Y leftward until you find one. For example, N = 425731; X = 425, Y = 731, a = 5, evenExist = false. Extend Y to get Y = 5731, X = 42, a = 2.
Find the smallest digit in Y that is greater than a. For N = 8234 | 961, a = 4, b = 6.
Swap a and b. After swapping: N = 8236 | 941; X = 8236, Y = 941.
Find the largest even digit in Y. For N = 8236 | 941, X = 8236, Y = 941, max even = 4. If there is no even digit in Y after swapping, extend Y further left until you find one. For example, 125831.
Swap the largest even digit with the rightmost digit. After swapping: N = 8236 | 914; X = 8236, Y = 914.
Sort the remaining digits in Y (except the rightmost) in ascending order. For N = 8236 | 91 | 4, after sorting: N = 8236 | 19 | 4.
The final result, N = xy, is the next even permutation.
classSolution {
// Swap two elements in the array if indices are valid and not the sameprivatevoidswap(int[] a, int i, int j) {
if (i == j || i < 0 || j < 0 || i >= a.length|| j >= a.length) {
return;
}
a[i]^= a[j];
a[j]^= a[i];
a[i]^= a[j];
}
/**
* Finds the next even permutation of the given digits array.
* Returns null if no such permutation exists.
*/publicint[]nextEven(int[] digits) {
int y = digits.length- 1;
boolean evenFound = digits[y]% 2 == 0;
// Find the longest non-increasing suffix from the rightfor (int i = digits.length- 2; i >= 0; i--) {
if (digits[i]>= digits[i + 1]) {
evenFound |= digits[i]% 2 == 0;
y = i;
} else {
break;
}
}
int maxEven =-1;
// If the suffix does not contain an even digit, extend it left until one is foundwhile (!evenFound && y - 1 >= 0 && digits[y - 1]% 2 != 0) {
y--;
}
// If already at the largest permutation, check if last digit is evenif (y <= 0) {
return digits[digits.length- 1]% 2 == 0 ? digits : null;
}
// Try to extend the suffix so that it contains an even digit after swappingwhile (y - 1 >= 0) {
// X = digits[0..y-1], Y = digits[y..digits.length-1]// a is the last element of X// Find b: the smallest digit in Y greater than aint a = y - 1;
int b =-1;
for (int i = y; i < digits.length; i++) {
if (digits[i]> digits[a]&& (b ==-1 || digits[i]< digits[b])) {
b = i;
}
}
// If no valid b found, check if last digit is evenif (b ==-1) {
return digits[digits.length- 1]% 2 == 0 ? digits : null;
}
// Swap a and b swap(digits, a, b);
// Find the largest even digit in the suffix maxEven =-1;
for (int i = y; i < digits.length; i++) {
if (digits[i]% 2 == 0 && (maxEven ==-1 || digits[i]> digits[maxEven])) {
maxEven = i;
}
}
// If no even digit found, extend the suffix further leftif (maxEven ==-1) {
y--;
} else {
break;
}
}
if (maxEven ==-1) {
return digits[digits.length- 1]% 2 == 0 ? digits : null;
}
// Swap the largest even digit with the rightmost digit swap(digits, maxEven, digits.length- 1);
// Sort the suffix except the rightmost digit Arrays.sort(digits, y, digits.length- 1);
return digits;
}
}
#include<vector>#include<algorithm>classSolution {
private:// Swap two elements in the array if indices are valid and not the same
void swap(std::vector<int>& a, int i, int j) {
if (i == j || i <0|| j <0|| i >= a.size() || j >= a.size()) return;
std::swap(a[i], a[j]);
}
public:// Finds the next even permutation of the given digits array.
// Returns empty vector if no such permutation exists.
std::vector<int> nextEven(std::vector<int> digits) {
int y = digits.size() -1;
bool evenFound = digits[y] %2==0;
// Find the longest non-increasing suffix from the right
for (int i = digits.size() -2; i >=0; i--) {
if (digits[i] >= digits[i +1]) {
evenFound |= digits[i] %2==0;
y = i;
} else {
break;
}
}
int maxEven =-1;
// If the suffix does not contain an even digit, extend it left until one is found
while (!evenFound && y -1>=0&& digits[y -1] %2!=0) {
y--;
}
// If already at the largest permutation, check if last digit is even
if (y <=0) {
return digits[digits.size() -1] %2==0? digits : std::vector<int>();
}
// Try to extend the suffix so that it contains an even digit after swapping
while (y -1>=0) {
int a = y -1;
int b =-1;
for (int i = y; i < digits.size(); i++) {
if (digits[i] > digits[a] && (b ==-1|| digits[i] < digits[b])) {
b = i;
}
}
if (b ==-1) {
return digits[digits.size() -1] %2==0? digits : std::vector<int>();
}
swap(digits, a, b);
maxEven =-1;
for (int i = y; i < digits.size(); i++) {
if (digits[i] %2==0&& (maxEven ==-1|| digits[i] > digits[maxEven])) {
maxEven = i;
}
}
if (maxEven ==-1) {
y--;
} else {
break;
}
}
if (maxEven ==-1) {
return digits[digits.size() -1] %2==0? digits : std::vector<int>();
}
swap(digits, maxEven, digits.size() -1);
std::sort(digits.begin() + y, digits.end() -1);
return digits;
}
};
from typing import List
classSolution:
defswap(self, a: List[int], i: int, j: int):
if i == j or i <0or j <0or i >= len(a) or j >= len(a):
return a[i], a[j] = a[j], a[i]
defnextEven(self, digits: List[int]) -> List[int] orNone:
y = len(digits) -1 even_found = digits[y] %2==0# Find the longest non-increasing suffix from the rightfor i in range(len(digits) -2, -1, -1):
if digits[i] >= digits[i +1]:
even_found |= digits[i] %2==0 y = i
else:
break max_even =-1# If the suffix does not contain an even digit, extend it left until one is foundwhilenot even_found and y -1>=0and digits[y -1] %2!=0:
y -=1# If already at the largest permutation, check if last digit is evenif y <=0:
return digits if digits[-1] %2==0elseNone# Try to extend the suffix so that it contains an even digit after swappingwhile y -1>=0:
a = y -1 b =-1for i in range(y, len(digits)):
if digits[i] > digits[a] and (b ==-1or digits[i] < digits[b]):
b = i
if b ==-1:
return digits if digits[-1] %2==0elseNone self.swap(digits, a, b)
max_even =-1for i in range(y, len(digits)):
if digits[i] %2==0and (max_even ==-1or digits[i] > digits[max_even]):
max_even = i
if max_even ==-1:
y -=1else:
breakif max_even ==-1:
return digits if digits[-1] %2==0elseNone self.swap(digits, max_even, len(digits) -1)
digits[y:len(digits) -1] = sorted(digits[y:len(digits) -1])
return digits
⏰ Time complexity: O(n^2) — The algorithm may scan and sort subarrays multiple times in the worst case.
🧺 Space complexity: O(n) — Uses extra space for the digits array/list and sorting.