eBook – Guide Spring Cloud – NPI EA (cat=Spring Cloud)
announcement - icon

Let's get started with a Microservice Architecture with Spring Cloud:

>> Join Pro and download the eBook

eBook – Mockito – NPI EA (tag = Mockito)
announcement - icon

Mocking is an essential part of unit testing, and the Mockito library makes it easy to write clean and intuitive unit tests for your Java code.

Get started with mocking and improve your application tests using our Mockito guide:

Download the eBook

eBook – Java Concurrency – NPI EA (cat=Java Concurrency)
announcement - icon

Handling concurrency in an application can be a tricky process with many potential pitfalls. A solid grasp of the fundamentals will go a long way to help minimize these issues.

Get started with understanding multi-threaded applications with our Java Concurrency guide:

>> Download the eBook

eBook – Reactive – NPI EA (cat=Reactive)
announcement - icon

Spring 5 added support for reactive programming with the Spring WebFlux module, which has been improved upon ever since. Get started with the Reactor project basics and reactive programming in Spring Boot:

>> Join Pro and download the eBook

eBook – Java Streams – NPI EA (cat=Java Streams)
announcement - icon

Since its introduction in Java 8, the Stream API has become a staple of Java development. The basic operations like iterating, filtering, mapping sequences of elements are deceptively simple to use.

But these can also be overused and fall into some common pitfalls.

To get a better understanding on how Streams work and how to combine them with other language features, check out our guide to Java Streams:

>> Join Pro and download the eBook

eBook – Jackson – NPI EA (cat=Jackson)
announcement - icon

Do JSON right with Jackson

Download the E-book

eBook – HTTP Client – NPI EA (cat=Http Client-Side)
announcement - icon

Get the most out of the Apache HTTP Client

Download the E-book

eBook – Maven – NPI EA (cat = Maven)
announcement - icon

Get Started with Apache Maven:

Download the E-book

eBook – Persistence – NPI EA (cat=Persistence)
announcement - icon

Working on getting your persistence layer right with Spring?

Explore the eBook

eBook – RwS – NPI EA (cat=Spring MVC)
announcement - icon

Building a REST API with Spring?

Download the E-book

Course – LS – NPI EA (cat=Jackson)
announcement - icon

Get started with Spring and Spring Boot, through the Learn Spring course:

>> LEARN SPRING
Course – RWSB – NPI EA (cat=REST)
announcement - icon

Explore Spring Boot 3 and Spring 6 in-depth through building a full REST API with the framework:

>> The New “REST With Spring Boot”

Course – LSS – NPI EA (cat=Spring Security)
announcement - icon

Yes, Spring Security can be complex, from the more advanced functionality within the Core to the deep OAuth support in the framework.

I built the security material as two full courses - Core and OAuth, to get practical with these more complex scenarios. We explore when and how to use each feature and code through it on the backing project.

You can explore the course here:

>> Learn Spring Security

Course – LSD – NPI EA (tag=Spring Data JPA)
announcement - icon

Spring Data JPA is a great way to handle the complexity of JPA with the powerful simplicity of Spring Boot.

Get started with Spring Data JPA through the guided reference course:

>> CHECK OUT THE COURSE

Partner – Moderne – NPI EA (cat=Spring Boot)
announcement - icon

Refactor Java code safely — and automatically — with OpenRewrite.

Refactoring big codebases by hand is slow, risky, and easy to put off. That’s where OpenRewrite comes in. The open-source framework for large-scale, automated code transformations helps teams modernize safely and consistently.

Each month, the creators and maintainers of OpenRewrite at Moderne run live, hands-on training sessions — one for newcomers and one for experienced users. You’ll see how recipes work, how to apply them across projects, and how to modernize code with confidence.

Join the next session, bring your questions, and learn how to automate the kind of work that usually eats your sprint time.

Partner – LambdaTest – NPI EA (cat=Testing)
announcement - icon

Regression testing is an important step in the release process, to ensure that new code doesn't break the existing functionality. As the codebase evolves, we want to run these tests frequently to help catch any issues early on.

The best way to ensure these tests run frequently on an automated basis is, of course, to include them in the CI/CD pipeline. This way, the regression tests will execute automatically whenever we commit code to the repository.

In this tutorial, we'll see how to create regression tests using Selenium, and then include them in our pipeline using GitHub Actions:, to be run on the LambdaTest cloud grid:

>> How to Run Selenium Regression Tests With GitHub Actions

Course – LJB – NPI EA (cat = Core Java)
announcement - icon

Code your way through and build up a solid, practical foundation of Java:

>> Learn Java Basics

1. Introduction

In this tutorial, we’ll learn how to find the next higher number with the same set of digits as the original number in Java. This problem can be solved by using the concept of permutation, sorting, and a two-pointer approach.

2. Problem Statement

Given a positive integer, we need to find the next higher number that uses the exact same set of digits. For example, if the input is 123, we aim to rearrange its digits to form the next higher number with the same digits. In this case, the next higher number would be 132.

If the input is 654 or 444, then we return -1 to indicate that there is no next higher number possible.

3. Using Permutation

In this approach, we’ll utilize permutation to find the next greater number with the same digits as the input number. We’ll generate all possible permutations of the digits in the input number and add them to a TreeSet to ensure uniqueness and ordering. 

3.1. Implementation

First, we implement a method findPermutations() to generate all permutations of the digits in the input number num and add them to a TreeSet:

void findPermutations(int num, int index, StringBuilder sb, Set<Integer> hs) {
    if (index == String.valueOf(num).length()) {
        hs.add(Integer.parseInt(sb.toString()));
        return;
    }
    //...
}

The method first checks if the current index is equal to the length of the input number. If so, it means that a permutation has been fully generated, then we add the permutation to the TreeSet and return to end the recursion.

Otherwise, we iterate over the digits of the number starting from the current index to generate all the permutations:

for (int i = index; i < String.valueOf(num).length(); i++) {
    char temp = sb.charAt(index);
    sb.setCharAt(index, sb.charAt(i));
    sb.setCharAt(i, temp);
    //...
}

At each iteration, we swap the character at the current index index with the character at the iteration index i. This swapping action effectively creates different combinations of digits.

Following the swapping, the method recursively calls itself, with the updated index and the modified StringBuilder:

findPermutations(num, index + 1, sb, hs);
temp = sb.charAt(index);
sb.setCharAt(index, sb.charAt(i));
sb.setCharAt(i, temp); // Swap back after recursion

After the recursive call, we swap the characters back to their original positions to maintain the integrity of sb for subsequent iterations.

Let’s encapsulate the logic within a method:

int findNextHighestNumberUsingPermutation(int num) {
    Set<Integer> hs = new TreeSet();
    StringBuilder sb = new StringBuilder(String.valueOf(num));
    findPermutations(num, 0, sb, hs);
    for (int n : hs) {
        if (n > num) {
            return n;
        }
    }
    return -1;
}

Once all permutations are generated, we iterate through the TreeSet to find the smallest number greater than the input number. If such a number is found, it’s the next greater number. Otherwise, we return -1 to indicate that no such number exists.

3.2. Testing

Let’s validate the permutation solution:

assertEquals(536497, findNextHighestNumberUsingPermutation(536479));
assertEquals(-1, findNextHighestNumberUsingPermutation(987654));

3.3. Complexity Analysis

The time complexity of this implementation is O(n!) in the worst case, where n is the number of digits in the input number. The findPermutations() function generates all possible permutations of the digits n!, which remains the dominant factor in time complexity.

While TreeSet provides logarithmic complexity (log n) for insertion and retrieval, it doesn’t significantly impact the overall time complexity.

In the worst case, where all permutations are unique (no duplicates), the TreeSet could potentially hold all n! permutations of the digits. This leads to a space complexity of O(n!).

4. Using Sorting

In this method, we’ll employ a sorting approach to determine the next greater number with the same digits as the given input number.

4.1. Implementation

We begin by defining a method named findNextHighestNumberUsingSorting():

int findNextHighestNumberUsingSorting(int num) {
    String numStr = String.valueOf(num);
    char[] numChars = numStr.toCharArray();
    int pivotIndex;
    // ...
}

Inside the method, we convert the input number into a string and then into a character array. We also initialize a variable pivotIndex to identify the pivot point.

Next, we iterate over the numChars array from the rightmost digit to the left to identify the largest digit that is smaller than or equal to its right neighbor:

for (pivotIndex = numChars.length - 1; pivotIndex > 0; pivotIndex--) {
    if (numChars[pivotIndex] > numChars[pivotIndex - 1]) {
        break;
    }
}

This digit becomes the pivot point to identify the breaking point in the descending order of digits. If this condition is true, it means we’ve found a digit that is larger than its neighbor to the left (potential pivot). Then we break the loop because we don’t need to search further for a larger descending digit.

If no such pivot is found, it means that the number is already in descending order, therefore we return -1:

if (pivotIndex == 0) {
    return -1;
}

After identifying the pivot, the code searches for the smallest digit to the right of the pivot that is still greater than the pivot itself:

int pivot = numChars[pivotIndex - 1];
int minIndex = pivotIndex;

for (int j = pivotIndex + 1; j < numChars.length; j++) {
    if (numChars[j] > pivot && numChars[j] < numChars[minIndex]) {
        minIndex = j;
    }
}

This digit are swapped with the pivot later to create the next larger number. We iterate through the array starting from one position after the pivot using a loop to find the smallest digit that is greater than the pivot.

Once the minimum digit greater than the pivot is found, we swap its position with the pivot:

swap(numChars, pivotIndex - 1, minIndex);

This swap essentially brings the smallest digit that can be greater than the pivot to the position right before the pivot.

To create the next lexicographically larger number, the code needs to sort the digits to the right of the pivot in ascending order:

Arrays.sort(numChars, pivotIndex, numChars.length);
return Integer.parseInt(new String(numChars));

This results in the smallest permutation of the digits that is greater than the original number.

4.2. Testing

Now, let’s validate our sorting implementation:

assertEquals(536497, findNextHighestNumberUsingSorting(536479));
assertEquals(-1, findNextHighestNumberUsingSorting(987654));

In the first test case, the pivot is found at the index 4 (digit 7). Next, to find the smallest digit larger than the pivot (7), we iterate from pivotIndex + 1 to the end. 9 is greater than pivot (7) so the minimum digit greater than the pivot is found at the index 5 (digit 9).

Now, we swap numChars[4] (7) with numChars[5] (9). After we do the swapping and sorting, the numChars array becomes [5, 3, 6, 4, 9, 7].

4.3. Complexity Analysis

The time complexity of this implementation is O(n log n) and the space complexity is O(n). This is because the implementation of sorting the digits is in O(n log n) time and uses a character array to store the digits.

5. Using Two Pointers

This approach is more efficient than sorting. It utilizes two pointers to find the desired digits and manipulate them for the next higher number.

5.1. Implementation

Before we start the main logic, we create two helper methods to simplify the manipulation of characters within the array:

void swap(char[] numChars, int i, int j) {
    char temp = numChars[i];
    numChars[i] = numChars[j];
    numChars[j] = temp;
}

void reverse(char[] numChars, int i, int j) {
    while (i < j) {
        swap(numChars, i, j);
        i++;
        j--;
    }
}

Then we begin by defining a method named findNextHighestNumberUsingTwoPointer():

int findNextHighestNumberUsingTwoPointer (int num) {
    String numStr = String.valueOf(num);
    char[] numChars = numStr.toCharArray();
    int pivotIndex = numChars.length - 2;
    int minIndex = numChars.length - 1;
    // ...
}

Inside the method,  we convert the input number to a character array and initialize two variables:

  • pivotIndex: to track the pivot index from the right side of the array
  • minIndex: to find a digit greater than the pivot

We initialize the pivotIndex to the second last digit because if starts from the last digit (i.e., numChars.length – 1), there’s no digit to its right to compare it with. Subsequently, we use a while loop to find the first index pivotIndex from the right that has a digit smaller than or equal to the digit to its right: 

while (pivotIndex >= 0 && numChars[pivotIndex] >= numChars[pivotIndex+1]) {
    pivotIndexi--;
}

If the current digit is smaller, it means we’ve found the pivot point where the increasing trend breaks. Then the loop will be terminated.

If no such index is found, it means that the input number is the largest possible permutation, and there is no greater permutation possible:

if (pivotIndex == -1) {
    result = -1;
    return;
}

Otherwise, we use another while loop to find the first index minIndex from the right that has a digit that’s greater than the pivot digit pivotIndex:

while (numChars[minIndex] <= numChars[pivotIndex]) {
    minIndex--;
}

Next, we swap the digits at indices pivotIndex and minIndex using the swap() function:

swap(numChars, pivotIndex, minIndex);

This swap operation ensures that we explore different combinations of digits while generating permutations.

Finally, instead of sorting, we reverse the substring to the right of index pivotIndex to obtain the smallest permutation greater than the original number:

reverse(numChars, pivotIndex+1, numChars.length-1);
return Integer.parseInt(new String(numChars));

This effectively creates the smallest possible number greater than the original number using the remaining digits.

5.2. Testing

Let’s validate the two pointers implementation:

assertEquals(536497, findNextHighestNumberUsingSorting(536479));
assertEquals(-1, findNextHighestNumberUsingSorting(987654));

In the first test case, the pivotIndex remains as its initialized value (4) because numChars[4] (7) isn’t greater than numChars[5] (9). Therefore, the while loop breaks immediately.

In the second while loop, minIndex remains as its initialize value (5) as the numChars[5] (9) is not smaller than numChars[4] (7). Again, the while loop terminated.

Next, we swap numChars[4] (7) with numChars[5] (9). Since pivotIndex + 1 is 5 and minIndex is also 5, no reversing is needed. The numChars array becomes [5, 3, 6, 4, 9, 7].

5.3. Complexity Analysis

In the worst case, the loops iterating over the digits might traverse the entire character array numChars twice. This can happen when the input number is already in descending order (e.g., 987654).

Therefore, the time complexity of the function is O(n). Moreover, the space complexity is O(1) because it uses a constant amount of extra space for pointers and temporary variables.

6. Summary

Here’s a table summarizing the comparison of the three approaches and recommended use cases:

Approach Time Complexity Space Complexity Use Case
Permutation O(n!) O(n!) Use when the input number has a small number of digits
Sorting O(n log n) O(n) Use when the simplicity of implementation is important
Two Pointers O(n) O(1) Use when the input number has a large number of digits

7. Conclusion

In this article, we’ve explored three different approaches to finding the next higher number with the same set of digits as the original number in Java. Overall, the two-pointer approach offers a good balance between efficiency and simplicity for finding the next higher number with the same set of digits.

The code backing this article is available on GitHub. Once you're logged in as a Baeldung Pro Member, start learning and coding on the project.
Baeldung Pro – NPI EA (cat = Baeldung)
announcement - icon

Baeldung Pro comes with both absolutely No-Ads as well as finally with Dark Mode, for a clean learning experience:

>> Explore a clean Baeldung

Once the early-adopter seats are all used, the price will go up and stay at $33/year.

eBook – HTTP Client – NPI EA (cat=HTTP Client-Side)
announcement - icon

The Apache HTTP Client is a very robust library, suitable for both simple and advanced use cases when testing HTTP endpoints. Check out our guide covering basic request and response handling, as well as security, cookies, timeouts, and more:

>> Download the eBook

eBook – Java Concurrency – NPI EA (cat=Java Concurrency)
announcement - icon

Handling concurrency in an application can be a tricky process with many potential pitfalls. A solid grasp of the fundamentals will go a long way to help minimize these issues.

Get started with understanding multi-threaded applications with our Java Concurrency guide:

>> Download the eBook

eBook – Java Streams – NPI EA (cat=Java Streams)
announcement - icon

Since its introduction in Java 8, the Stream API has become a staple of Java development. The basic operations like iterating, filtering, mapping sequences of elements are deceptively simple to use.

But these can also be overused and fall into some common pitfalls.

To get a better understanding on how Streams work and how to combine them with other language features, check out our guide to Java Streams:

>> Join Pro and download the eBook

eBook – Persistence – NPI EA (cat=Persistence)
announcement - icon

Working on getting your persistence layer right with Spring?

Explore the eBook

Course – LS – NPI EA (cat=REST)

announcement - icon

Get started with Spring Boot and with core Spring, through the Learn Spring course:

>> CHECK OUT THE COURSE

Partner – Moderne – NPI EA (tag=Refactoring)
announcement - icon

Modern Java teams move fast — but codebases don’t always keep up. Frameworks change, dependencies drift, and tech debt builds until it starts to drag on delivery. OpenRewrite was built to fix that: an open-source refactoring engine that automates repetitive code changes while keeping developer intent intact.

The monthly training series, led by the creators and maintainers of OpenRewrite at Moderne, walks through real-world migrations and modernization patterns. Whether you’re new to recipes or ready to write your own, you’ll learn practical ways to refactor safely and at scale.

If you’ve ever wished refactoring felt as natural — and as fast — as writing code, this is a good place to start.

eBook Jackson – NPI EA – 3 (cat = Jackson)