A clear explanation of Next Greater Element III using the next permutation algorithm on the digits of an integer.
Problem Restatement
We are given a positive integer n.
We need to rearrange its digits to form the smallest integer that is greater than n.
The new integer must use exactly the same digits as n.
If no greater integer can be formed, return -1.
If the answer is greater than the 32-bit signed integer limit, return -1.
The official constraint is:
1 <= n <= 2**31 - 1The return value must also fit inside:
2**31 - 1The problem examples include n = 12, output 21, and n = 21, output -1. The statement requires the smallest greater integer using exactly the same digits.
Input and Output
| Item | Meaning |
|---|---|
| Input | A positive integer n |
| Output | The next greater integer using the same digits |
Return -1 when | No greater arrangement exists |
Return -1 when | The answer exceeds 2^31 - 1 |
Example function shape:
def nextGreaterElement(n: int) -> int:
...Examples
Example 1:
n = 12The digits are:
["1", "2"]The only greater arrangement is:
21So the answer is:
21Example 2:
n = 21The digits are already in descending order:
2, 1There is no way to rearrange them into a greater number.
So the answer is:
-1Example 3:
n = 12443322We want the next greater number, not just any greater number.
The answer is:
13222344First Thought: Try All Permutations
One direct idea is to generate every permutation of the digits.
Then we can keep only the numbers greater than n, sort them, and return the smallest one.
This is correct for small inputs, but it is too expensive.
If n has d digits, there can be up to:
d!permutations.
A 32-bit integer has at most 10 digits, so this may look possible, but handling duplicates, sorting, and converting many permutations is unnecessary. There is a direct linear algorithm.
Key Insight
This is the same idea as the classic next permutation algorithm.
We want the next number in lexicographic order of digit sequences.
To make the number just slightly larger, we should change the number as far to the right as possible.
Consider:
n = 12443322Digits:
1 2 4 4 3 3 2 2Scan from right to left and find the first position where a digit is smaller than the digit after it.
That position is the pivot.
Here:
2 < 4at the second digit.
The suffix after that pivot is:
4 4 3 3 2 2This suffix is in descending order, which means it is already the largest possible arrangement for those digits. To get the next greater number, we must increase the pivot slightly, then make the suffix as small as possible.
Algorithm
Convert n to a list of digit characters.
Find the pivot:
- Start from the second-to-last digit.
- Move left while
digits[i] >= digits[i + 1]. - If no pivot exists, return
-1.
Find the swap digit:
- Start from the last digit.
- Move left until finding a digit greater than
digits[i].
Swap the pivot and the swap digit.
Reverse the suffix after the pivot.
Convert the digits back to an integer.
If the result is greater than
2^31 - 1, return-1. Otherwise, return the result.
Why Reversing the Suffix Works
Before the swap, the suffix after the pivot is in descending order.
After we swap the pivot with the smallest possible larger digit from the suffix, the suffix is still in descending order.
To get the smallest number greater than the original, the suffix must become as small as possible.
For digits, the smallest order is ascending order.
Since the suffix is descending, reversing it makes it ascending.
Correctness
The algorithm finds the rightmost pivot i such that:
digits[i] < digits[i + 1]Every digit after i forms a non-increasing suffix. This means the suffix is already the largest possible arrangement of those suffix digits. Therefore, no rearrangement only inside the suffix can make the number greater.
So any greater number using the same digits must change position i or some earlier position. To make the increase as small as possible, we change the rightmost possible position, which is exactly i.
Next, the algorithm chooses the rightmost digit greater than digits[i]. Because the suffix is non-increasing, this is the smallest digit in the suffix that is still greater than the pivot. Swapping with it gives the smallest possible increase at position i.
Finally, the algorithm reverses the suffix to make it ascending. This produces the smallest possible suffix after increasing the pivot.
Therefore, the result is greater than n, uses exactly the same digits, and is the smallest such integer. If no pivot exists, all digits are in descending order, so no greater arrangement exists.
Complexity
Let d be the number of digits in n.
| Metric | Value | Why |
|---|---|---|
| Time | O(d) | We scan and reverse the digit list |
| Space | O(d) | We store the digits as a list |
Since n is a 32-bit integer, d <= 10, but the algorithm is still linear in the number of digits.
Implementation
class Solution:
def nextGreaterElement(self, n: int) -> int:
digits = list(str(n))
length = len(digits)
i = length - 2
while i >= 0 and digits[i] >= digits[i + 1]:
i -= 1
if i < 0:
return -1
j = length - 1
while digits[j] <= digits[i]:
j -= 1
digits[i], digits[j] = digits[j], digits[i]
digits[i + 1:] = reversed(digits[i + 1:])
ans = int("".join(digits))
if ans > 2**31 - 1:
return -1
return ansCode Explanation
We first convert the integer into a mutable list:
digits = list(str(n))Then we find the pivot:
i = length - 2
while i >= 0 and digits[i] >= digits[i + 1]:
i -= 1If no pivot exists, the digits are in descending order:
if i < 0:
return -1Then we find the digit to swap with the pivot:
j = length - 1
while digits[j] <= digits[i]:
j -= 1Because the suffix is descending, scanning from the right finds the smallest digit greater than the pivot.
Then we swap:
digits[i], digits[j] = digits[j], digits[i]Finally, we reverse the suffix:
digits[i + 1:] = reversed(digits[i + 1:])This makes the suffix as small as possible.
After rebuilding the integer, we check the 32-bit limit:
ans = int("".join(digits))
if ans > 2**31 - 1:
return -1Testing
def run_tests():
s = Solution()
assert s.nextGreaterElement(12) == 21
assert s.nextGreaterElement(21) == -1
assert s.nextGreaterElement(123) == 132
assert s.nextGreaterElement(12443322) == 13222344
assert s.nextGreaterElement(1999999999) == -1
assert s.nextGreaterElement(230241) == 230412
assert s.nextGreaterElement(115) == 151
assert s.nextGreaterElement(9) == -1
print("all tests passed")
run_tests()| Test | Why |
|---|---|
12 | Smallest sample with a valid answer |
21 | Digits already descending |
123 | Simple next permutation |
12443322 | Larger case with repeated digits |
1999999999 | Next arrangement exceeds 32-bit limit |
230241 | Pivot occurs near the middle |
115 | Repeated digit handling |
9 | Single digit cannot form a greater number |