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.

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

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

Distributed systems often come with complex challenges such as service-to-service communication, state management, asynchronous messaging, security, and more.

Dapr (Distributed Application Runtime) provides a set of APIs and building blocks to address these challenges, abstracting away infrastructure so we can focus on business logic.

In this tutorial, we'll focus on Dapr's pub/sub API for message brokering. Using its Spring Boot integration, we'll simplify the creation of a loosely coupled, portable, and easily testable pub/sub messaging system:

>> Flexible Pub/Sub Messaging With Spring Boot and Dapr

1. Overview

In this tutorial, we’ll explore different ways to generate all possible IP Addresses from a given numeric string in Java. This problem is a common interview question. We’ll first deep-dive into the problem statement and then cover several techniques to solve it, including brute force, backtracking, and dynamic programming.

2. Understanding the Problem Statement

We’re given a string S which contains only digits, the goal is to find and return all possible valid IP addresses that can be formed by inserting dots into S. We can’t remove or reorder any digits; the result can be returned in any order.

For example, for a given string “101024”, we’ll have the following output:

["1.0.10.24","1.0.102.4","10.1.0.24","10.10.2.4","101.0.2.4"]

The output above lists all the valid IP addresses the given string can form. A valid IPv4 address consists of four octets separated by dots. Each octet is a number between 0 and 255. This means that a valid IPv4 address looks like:

0.0.0.0
192.168.0.8
234.223.43.42
255.255.255.0

3. Iterative Approach

In this approach, we’ll use three nested loops to iterate through possible positions to split the string into four parts. The outer loop iterates over the first part, the middle loop over the second part, and the inner loop over the third part. We’ll consider the remaining part of the string as the fourth segment.

Once we’ve got the segment combinations, we’ll extract sub-strings and validate each segment to determine if it forms a valid part of an IP address using the isValid() method. The isValid() method is responsible for checking if a given string is a valid part of an IP address or not. It makes sure that the integer value is between 0 and 255 and that it doesn’t have a leading zero:

public List<String> restoreIPAddresses(String s) {
    List<String> result = new ArrayList<>();

    if (s.length() < 4 || s.length() > 12) {
        return result;
    }

    for (int i = 1; i < 4; i++) {
        for (int j = i + 1; j < Math.min(i + 4, s.length()); j++) {
            for (int k = j + 1; k < Math.min(j + 4, s.length()); k++) {
                String part1 = s.substring(0, i);
                String part2 = s.substring(i, j);
                String part3 = s.substring(j, k);
                String part4 = s.substring(k);

                if (isValid(part1) && isValid(part2) && isValid(part3) && isValid(part4)) {
                    result.add(part1 + "." + part2 + "." + part3 + "." + part4);
                }
            }
        }
    }
    return result;
}

private boolean isValid(String part) {
    if (part.length() > 1 && part.startsWith("0")) {
return false;
} int num = Integer.parseInt(part); return num >= 0 && num <= 255; }

The method restoreIPAddresses() generates and returns all possible valid IP addresses. It also checks whether the string length falls outside the range of 4, and 12 characters and returns an empty list if it does, as a valid IP address can’t be formed in that case. 

We’re using nested loops to iterate over all possible positions for the three dots. This increases the time complexity to O(n2). It’s not O(n3) because the outer loop has a fixed number of iterations. Also, we’re creating temporary sub-strings during each iteration, which increases the overall space complexity to O(n).

4. Backtracking Approach

When backtracking, we generate all possible IP addresses by splitting the string into four parts. At each step, we perform the validation using the same isValid() method to check whether the string is non-empty and doesn’t have leading zeroes. If it’s a valid string we go to the next part. Once we’ve all four parts and have used all the characters, we’ll add them to the result list:

public List<String> restoreIPAddresses(String s) {
    List<String> result = new ArrayList<>();
    backtrack(result, s, new ArrayList<>(), 0);
    return result;
}

private void backtrack(List<String> result, String s, List<String> current, int index) {
    if (current.size() == 4) {
        if (index == s.length()) {
            result.add(String.join(".", current));
        }
        return;
    }

    for (int len = 1; len <= 3; len++) {
        if (index + len > s.length()) {
break; }
String part = s.substring(index, index + len); if (isValid(part)) { current.add(part); backtrack(result, s, current, index + len); current.remove(current.size() - 1); } } }

The backtrack function splits the string into 4 integer segments, each at most 3 digits long. This leads to 34 possible ways to split the string. Evaluating whether each segment is valid takes O(1) time, as it involves checking the length and range of the segment. Since the number of possible configurations 34 is constant and doesn’t depend on the input string length, the time complexity simplifies to O(1).

The recursion depth is limited to 4 because there are exactly 4 segments in an IP address. Therefore, the space complexity simplifies to O(1) since the number of configurations and the space required are constants.

5. Dynamic Programming Approach

Dynamic programming is a popular algorithmic paradigm that uses a recurrent formula to find the solution. It is similar to the divide-and-conquer strategy because it breaks down the problem into smaller sub-problems. Its solutions use arrays to store the results of previously calculated values.

Now, we’ll use a dp array to store all valid IP prefixes. We’ll first initialize a 2D list dp where dp[i][j] stores all possible IP address segments up to the ith character with j segments. After this, we check for all possible segment lengths (1 to 3) and validate each segment using the isValid() method. If a segment is valid, we append it to the prefixes from the previous state. We store and return the final result of valid IP addresses in dp[n][4].

public List<String> restoreIPAddresses(String s) {
    int n = s.length();
    if (n < 4 || n > 12) {
return new ArrayList<>(); }
List<String>[][] dp = new ArrayList[n + 1][5]; for (int i = 0; i <= n; i++) { for (int j = 0; j <= 4; j++) { dp[i][j] = new ArrayList<>(); } } dp[0][0].add(""); for (int i = 1; i <= n; i++) { for (int k = 1; k <= 4; k++) { for (int j = 1; j <= 3 && i - j >= 0; j++) { String segment = s.substring(i - j, i); if (isValid(segment)) { for (String prefix : dp[i - j][k - 1]) { dp[i][k].add(prefix.isEmpty() ? segment : prefix + "." + segment); } } } } } return dp[n][4]; }

Initialization of the dp array takes O(n*4) time, simplifying O(n). The nested loops responsible for filling the dp table take O(n*4*3) time simplifying to O(n). The space complexity is also O(n*4) which simplifies to O(n).

6. Conclusion

In this article, we discussed generating all possible IP address combinations from a given numeric string and understood various approaches to solve it. The iterative approach is straightforward but has a high time complexity O(n2). For better performance, we can use a dynamic programming approach which provides better time complexity of O(n).

The backtracking programming approach turned out to be the most efficient one as it had the best runtime O(1) amongst all the other approaches that we discussed.

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)