Facebook Pixel

556. Next Greater Element III

Problem Description

Given a positive integer n, find the smallest integer that:

  1. Contains exactly the same digits as n (using each digit the same number of times)
  2. Is greater in value than n

If no such integer exists, return -1.

Additionally, the returned integer must fit within a 32-bit signed integer range (maximum value of 2^31 - 1). If a valid answer exists but exceeds this range, return -1.

For example:

  • If n = 12, the next greater integer with the same digits is 21
  • If n = 21, no greater integer can be formed with digits 2 and 1, so return -1
  • If n = 123, the next greater integer is 132

The algorithm works by:

  1. Converting the number to a list of digit characters for manipulation
  2. Finding the rightmost digit that is smaller than its next digit (scanning from right to left) - this is the pivot point i
  3. If no such digit exists (digits are in descending order), no greater number is possible
  4. Finding the smallest digit to the right of position i that is still greater than cs[i] - this is position j
  5. Swapping the digits at positions i and j
  6. Reversing all digits after position i to get the smallest possible arrangement
  7. Checking if the result fits in 32-bit integer range before returning
Quick Interview Experience
Help others by sharing your interview experience
Have you seen this problem before?

Intuition

To find the next greater number with the same digits, think about how numbers increase in value. When we count: 123, 124, 125... each increment changes the rightmost digits first. But we're restricted to using only the existing digits.

Consider the number 12543. To make it bigger while using the same digits, we need to find where we can make a "smart swap". Reading from right to left, we see: 3, 4, 5, 2, 1. The digits 5, 4, 3 are in descending order - we can't rearrange them to make the number bigger without changing digits to their left. But when we reach 2, we notice that 2 < 5, meaning we can swap 2 with a larger digit to its right.

The key insight is finding the rightmost position where a digit is smaller than some digit to its right. This is our "pivot point" - position i. This digit at position i needs to be increased to make the overall number larger.

But we can't just swap with any larger digit. We want the next greater number, so we need to:

  1. Find the smallest digit to the right of i that's still larger than cs[i] - this gives us the minimal increase
  2. After swapping, the digits to the right of position i should be arranged in ascending order to create the smallest possible number with those remaining digits

For example, with 12543:

  • The pivot is at position 1 (digit 2)
  • The smallest digit greater than 2 to its right is 3
  • Swap: 13542
  • Sort remaining digits in ascending order: 13245

This approach guarantees we get the very next number in the sequence of all permutations of the given digits.

Learn more about Math and Two Pointers patterns.

Solution Approach

The implementation follows these steps:

  1. Convert to digit array: Convert the integer n to a list of character digits cs for easier manipulation. This allows us to work with individual digits and perform swaps.

  2. Find the pivot point: Starting from the second-to-last position (i = n - 2), scan leftward to find the first digit that is smaller than its right neighbor:

    while i >= 0 and cs[i] >= cs[i + 1]:
        i -= 1

    If i < 0, all digits are in non-increasing order (like 4321), meaning no greater permutation exists, so return -1.

  3. Find the swap target: From the rightmost position (j = n - 1), scan leftward to find the smallest digit that is still greater than cs[i]:

    while cs[i] >= cs[j]:
        j -= 1

    This ensures we get the minimal increase when we swap.

  4. Perform the swap: Exchange the digits at positions i and j:

    cs[i], cs[j] = cs[j], cs[i]
  5. Minimize the remaining digits: Reverse all digits after position i to arrange them in ascending order:

    cs[i + 1:] = cs[i + 1:][::-1]

    This works because after finding the pivot, all digits to its right were in descending order. After the swap, they remain in descending order, so reversing gives us ascending order - the smallest possible arrangement.

  6. Build and validate the result: Convert the digit array back to an integer and check if it fits within the 32-bit signed integer range (2^31 - 1):

    ans = int(''.join(cs))
    return -1 if ans > 2**31 - 1 else ans

The time complexity is O(n) where n is the number of digits, and space complexity is O(n) for storing the digit array.

Ready to land your dream job?

Unlock your dream job with a 3-minute evaluator for a personalized learning plan!

Start Evaluator

Example Walkthrough

Let's walk through the algorithm with n = 12543:

Step 1: Convert to digit array

  • cs = ['1', '2', '5', '4', '3']

Step 2: Find the pivot point (i)

  • Start from index 3 (second-to-last): cs[3] = '4', cs[4] = '3'
  • Is '4' >= '3'? Yes, so move left (i = 2)
  • Check index 2: cs[2] = '5', cs[3] = '4'
  • Is '5' >= '4'? Yes, so move left (i = 1)
  • Check index 1: cs[1] = '2', cs[2] = '5'
  • Is '2' >= '5'? No! We found our pivot at i = 1

Step 3: Find the swap target (j)

  • Start from the rightmost index 4: cs[4] = '3'
  • Is cs[1] = '2' >= '3'? No, so j = 4
  • We found the smallest digit greater than '2' to the right of position 1

Step 4: Perform the swap

  • Swap cs[1] and cs[4]: ['1', '3', '5', '4', '2']

Step 5: Minimize remaining digits

  • Reverse digits after position 1: cs[2:] = ['5', '4', '2']
  • After reversal: ['2', '4', '5']
  • Final array: ['1', '3', '2', '4', '5']

Step 6: Build and validate result

  • Convert to integer: 13245
  • Check if 13245 <= 2^31 - 1? Yes
  • Return 13245

The answer 13245 is indeed the next greater number using the same digits as 12543.

Solution Implementation

1class Solution:
2    def nextGreaterElement(self, n: int) -> int:
3        # Convert integer to list of digit characters for manipulation
4        digits = list(str(n))
5        length = len(digits)
6      
7        # Step 1: Find the rightmost digit that is smaller than its successor
8        # This is the pivot point where we need to make a change
9        pivot_index = length - 2
10        while pivot_index >= 0 and digits[pivot_index] >= digits[pivot_index + 1]:
11            pivot_index -= 1
12      
13        # If no such digit exists, the number is already the largest permutation
14        if pivot_index < 0:
15            return -1
16      
17        # Step 2: Find the smallest digit to the right of pivot that is larger than pivot
18        # This digit will be swapped with the pivot
19        swap_index = length - 1
20        while digits[pivot_index] >= digits[swap_index]:
21            swap_index -= 1
22      
23        # Step 3: Swap the pivot with the found digit
24        digits[pivot_index], digits[swap_index] = digits[swap_index], digits[pivot_index]
25      
26        # Step 4: Reverse all digits after the pivot position to get the smallest permutation
27        # This ensures we get the next greater number, not just any greater number
28        digits[pivot_index + 1:] = digits[pivot_index + 1:][::-1]
29      
30        # Convert the digit list back to an integer
31        result = int(''.join(digits))
32      
33        # Check if the result fits in a 32-bit signed integer
34        # Return -1 if it exceeds the maximum value (2^31 - 1)
35        return -1 if result > 2**31 - 1 else result
36
1class Solution {
2    public int nextGreaterElement(int n) {
3        // Convert number to character array for manipulation
4        char[] digits = String.valueOf(n).toCharArray();
5        int length = digits.length;
6      
7        // Step 1: Find the first digit from right that is smaller than its next digit
8        // This is the pivot point where we need to make a swap
9        int pivotIndex = length - 2;
10        while (pivotIndex >= 0 && digits[pivotIndex] >= digits[pivotIndex + 1]) {
11            pivotIndex--;
12        }
13      
14        // If no such digit found, the number is already the largest permutation
15        if (pivotIndex < 0) {
16            return -1;
17        }
18      
19        // Step 2: Find the smallest digit to the right of pivot that is larger than pivot
20        // This digit will be swapped with the pivot
21        int swapIndex = length - 1;
22        while (digits[pivotIndex] >= digits[swapIndex]) {
23            swapIndex--;
24        }
25      
26        // Step 3: Swap the pivot with the found digit
27        swap(digits, pivotIndex, swapIndex);
28      
29        // Step 4: Reverse all digits after pivot position to get the smallest arrangement
30        // This ensures we get the next greater number, not just any greater number
31        reverse(digits, pivotIndex + 1, length - 1);
32      
33        // Convert back to number and check for integer overflow
34        long result = Long.parseLong(String.valueOf(digits));
35        return result > Integer.MAX_VALUE ? -1 : (int) result;
36    }
37  
38    /**
39     * Helper method to swap two characters in an array
40     * @param digits the character array
41     * @param i first index to swap
42     * @param j second index to swap
43     */
44    private void swap(char[] digits, int i, int j) {
45        char temp = digits[i];
46        digits[i] = digits[j];
47        digits[j] = temp;
48    }
49  
50    /**
51     * Helper method to reverse a portion of the character array
52     * @param digits the character array
53     * @param start starting index (inclusive)
54     * @param end ending index (inclusive)
55     */
56    private void reverse(char[] digits, int start, int end) {
57        while (start < end) {
58            swap(digits, start, end);
59            start++;
60            end--;
61        }
62    }
63}
64
1class Solution {
2public:
3    int nextGreaterElement(int n) {
4        // Convert number to string for digit manipulation
5        string digits = to_string(n);
6        int length = digits.size();
7      
8        // Step 1: Find the rightmost digit that is smaller than its next digit
9        // This is the pivot point where we need to make a change
10        int pivotIndex = length - 2;
11        while (pivotIndex >= 0 && digits[pivotIndex] >= digits[pivotIndex + 1]) {
12            pivotIndex--;
13        }
14      
15        // If no such digit exists, the number is already the largest permutation
16        if (pivotIndex < 0) {
17            return -1;
18        }
19      
20        // Step 2: Find the smallest digit to the right of pivot that is larger than pivot
21        // This digit will be swapped with the pivot
22        int swapIndex = length - 1;
23        while (digits[pivotIndex] >= digits[swapIndex]) {
24            swapIndex--;
25        }
26      
27        // Step 3: Swap the pivot with the found digit
28        swap(digits[pivotIndex], digits[swapIndex]);
29      
30        // Step 4: Reverse all digits after the pivot position to get the smallest permutation
31        // This ensures we get the next greater element, not just any greater element
32        reverse(digits.begin() + pivotIndex + 1, digits.end());
33      
34        // Convert back to number and check for integer overflow
35        long result = stol(digits);
36      
37        // Return -1 if the result exceeds 32-bit integer range
38        return result > INT_MAX ? -1 : result;
39    }
40};
41
1function nextGreaterElement(n: number): number {
2    // Convert number to string for digit manipulation
3    const digits: string[] = n.toString().split('');
4    const length: number = digits.length;
5  
6    // Step 1: Find the rightmost digit that is smaller than its next digit
7    // This is the pivot point where we need to make a change
8    let pivotIndex: number = length - 2;
9    while (pivotIndex >= 0 && digits[pivotIndex] >= digits[pivotIndex + 1]) {
10        pivotIndex--;
11    }
12  
13    // If no such digit exists, the number is already the largest permutation
14    if (pivotIndex < 0) {
15        return -1;
16    }
17  
18    // Step 2: Find the smallest digit to the right of pivot that is larger than pivot
19    // This digit will be swapped with the pivot
20    let swapIndex: number = length - 1;
21    while (digits[pivotIndex] >= digits[swapIndex]) {
22        swapIndex--;
23    }
24  
25    // Step 3: Swap the pivot with the found digit
26    [digits[pivotIndex], digits[swapIndex]] = [digits[swapIndex], digits[pivotIndex]];
27  
28    // Step 4: Reverse all digits after the pivot position to get the smallest permutation
29    // This ensures we get the next greater element, not just any greater element
30    const leftPart: string[] = digits.slice(0, pivotIndex + 1);
31    const rightPart: string[] = digits.slice(pivotIndex + 1).reverse();
32    const resultDigits: string[] = [...leftPart, ...rightPart];
33  
34    // Convert back to number and check for integer overflow
35    const result: number = parseInt(resultDigits.join(''));
36  
37    // Return -1 if the result exceeds 32-bit integer range (2^31 - 1)
38    const MAX_INT: number = 2147483647;
39    return result > MAX_INT ? -1 : result;
40}
41

Time and Space Complexity

Time Complexity: O(d) where d is the number of digits in the input number

  • Converting integer to string: O(d)
  • First while loop to find the rightmost digit that's smaller than its next digit: O(d) in worst case
  • Second while loop to find the smallest digit greater than cs[i] from the right: O(d) in worst case
  • Swapping two elements: O(1)
  • Reversing the suffix cs[i+1:]: O(d) in worst case
  • Converting string back to integer: O(d)
  • Overall: O(d) + O(d) + O(d) + O(1) + O(d) + O(d) = O(d)

Space Complexity: O(d) where d is the number of digits in the input number

  • The list cs stores all digits of the input number: O(d)
  • The reversed suffix operation creates a new list temporarily: O(d)
  • String join operation creates a new string: O(d)
  • Overall auxiliary space: O(d)

Learn more about how to find time and space complexity quickly.

Common Pitfalls

1. Integer Overflow Not Handled Early

A common mistake is not checking for integer overflow before converting the final result. Some implementations might crash or produce incorrect results when the rearranged number exceeds the 32-bit limit.

Pitfall Example:

# Incorrect: May cause issues with very large numbers
result = int(''.join(digits))
return result  # Forgot to check overflow!

Solution: Always validate against 2^31 - 1 before returning:

result = int(''.join(digits))
return -1 if result > 2**31 - 1 else result

2. Incorrect Pivot Finding Logic

Many implementations incorrectly search for the pivot from left to right instead of right to left, which can miss the correct swap position.

Pitfall Example:

# Incorrect: Starting from the beginning
pivot_index = 0
while pivot_index < length - 1 and digits[pivot_index] >= digits[pivot_index + 1]:
    pivot_index += 1

Solution: Always scan from right to left to find the rightmost valid pivot:

pivot_index = length - 2
while pivot_index >= 0 and digits[pivot_index] >= digits[pivot_index + 1]:
    pivot_index -= 1

3. Not Finding the Optimal Swap Target

After finding the pivot, some solutions swap with any larger digit instead of the smallest digit that's still larger than the pivot, resulting in a number that's not the immediate next greater.

Pitfall Example:

# Incorrect: Just finding any larger digit
for j in range(pivot_index + 1, length):
    if digits[j] > digits[pivot_index]:
        swap_index = j
        break  # This might not be the optimal choice

Solution: Scan from right to left to find the smallest digit greater than the pivot:

swap_index = length - 1
while digits[pivot_index] >= digits[swap_index]:
    swap_index -= 1

4. Forgetting to Reverse After Swap

A critical mistake is forgetting to reverse the digits after the pivot position, which results in a larger number than necessary.

Pitfall Example:

# Incorrect: Just swapping without reversing
digits[pivot_index], digits[swap_index] = digits[swap_index], digits[pivot_index]
# Missing the reversal step!
result = int(''.join(digits))

Solution: Always reverse the suffix after swapping to minimize the result:

digits[pivot_index], digits[swap_index] = digits[swap_index], digits[pivot_index]
digits[pivot_index + 1:] = digits[pivot_index + 1:][::-1]

5. Edge Case: Single Digit Numbers

Not handling single-digit numbers properly can cause index out of bounds errors.

Pitfall Example:

# May fail for n = 5 (single digit)
pivot_index = length - 2  # This becomes -1 for single digits

Solution: The current implementation handles this correctly as the while loop condition pivot_index >= 0 prevents issues, and single digits will correctly return -1 since no greater permutation exists.

Discover Your Strengths and Weaknesses: Take Our 3-Minute Quiz to Tailor Your Study Plan:

Which of the following is a good use case for backtracking?


Recommended Readings

Want a Structured Path to Master System Design Too? Don’t Miss This!

Load More