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

The maximum subarray problem is a task to find the series of contiguous elements with the maximum sum in any given array.

For instance, in the below array, the highlighted subarray has the maximum sum(6):

Maximum Subarray

In this tutorial, we’ll take a look at two solutions for finding the maximum subarray in an array. One of which we’ll design with O(n) time and space complexity.

2. Brute Force Algorithm

Brute force is an iterative approach to solve a problem. In most cases, the solution requires a number of iterations over a data structure. In the next few sections, we’ll apply this approach to solve the maximum subarray problem.

2.1. Approach

Generally speaking, the first solution that comes to mind is to calculate the sum of every possible subarray and return the one with the maximum sum.

To begin with, we’ll calculate the sum of every subarray that starts at index 0. And similarly, we’ll find all subarrays starting at every index from 0 to n-1 where n is the length of the array:

Brute Force Algorithm

 

So we’ll start at index 0 and add every element to the running sum in the iteration. We’ll also keep track of the maximum sum seen so far. This iteration is shown on the left side of the image above.

On the right side of the image, we can see the iteration that starts at index 3. In the last part of this image, we’ve got the subarray with the maximum sum between index 3 and 6.

However, our algorithm will continue to find all subarrays starting at indices between 0 and n-1.

2.2. Implementation

Let’s now see how we can implement this solution in Java:

public int maxSubArray(int[] nums) {
 
    int n = nums.length;
    int maximumSubArraySum = Integer.MIN_VALUE;
    int start = 0;
    int end = 0;
 
    for (int left = 0; left < n; left++) {
 
        int runningWindowSum = 0;
 
        for (int right = left; right < n; right++) {
            runningWindowSum += nums[right];
 
            if (runningWindowSum > maximumSubArraySum) {
                maximumSubArraySum = runningWindowSum;
                start = left;
                end = right;
            }
        }
    }
    logger.info("Found Maximum Subarray between {} and {}", start, end);
    return maximumSubArraySum;
}

As expected, we update the maximumSubArraySum if the current sum is more than the previous maximum sum. Notably, we then also update the start and end to find out the index locations of this subarray.

2.3. Complexity

Generally speaking the brute force solution iterates over the array many times in order to get every possible solution. This means the time taken by this solution grows quadratically with the number of elements in the array. This may not be a problem for arrays of a small size. But as the size of the array grows, this solution isn’t efficient.

By inspecting the code, we can also see that there are two nested for loops. Therefore, we can conclude that the time complexity of this algorithm is O(n2).

In the later sections, we’ll solve this problem in O(n) complexity using dynamic programming.

3. Dynamic Programming

Dynamic programming solves a problem by dividing it into smaller subproblems. This is very similar to the divide-and-conquer algorithm solving technique. The major difference, however, is that dynamic programming solves a subproblem only once.

It then stores the result of this subproblem and later reuses this result to solve other related subproblems. This process is known as memoization.

3.1. Kadane’s Algorithm

Kadane’s algorithm is a popular solution to the maximum subarray problem and this solution is based on dynamic programming.

The most important challenge in solving a dynamic programming problem is to find the optimal subproblems.

3.2. Approach

Let’s understand this problem in a different way:

Kadane Algorithm

In the image above, we assume that the maximum subarray ends at the last index location. Therefore, the maximum sum of subarray will be:

maximumSubArraySum = max_so_far + arr[n-1]

max_so_far is the maximum sum of a subarray that ends at index n-2. This is also shown in the image above.

Now, we can apply this assumption to any index in the array. For example, the maximum subarray sum that ends at n-2 can be calculated as:

maximumSubArraySum[n-2] = max_so_far[n-3] + arr[n-2]

Therefore, we can conclude that:

maximumSubArraySum[i] = maximumSubArraySum[i-1] + arr[i]

Now, since every element in the array is a special subarray of size one, we also need to check if an element is greater than the maximum sum itself:

maximumSubArraySum[i] = Max(arr[i], maximumSubArraySum[i-1] + arr[i])

By looking at these equations, we can see that we need to find the maximum subarray sum at every index of the array. Thus, we divided our problem into n subproblems. We can find the maximum sum at every index by iterating the array only once:

Kadane Algorithm

The highlighted element shows the current element in the iteration. At every index, we’ll apply the equation derived earlier to calculate a value for max_ending_here. This helps us in identifying whether we should include the current element in the subarray or start a new subarray starting at this index.

Another variable, max_so_far is used to store the maximum subarray sum found during the iteration. Once we iterate over the last index, max_so_far will store the sum of the maximum subarray.

3.3. Implementation

Again, let’s see how we can now implement the Kadane algorithm in Java, following the above approach:

public int maxSubArraySum(int[] arr) {	
    int size = arr.length;	
    int start = 0;	
    int end = 0;	
    int maxSoFar = arr[0], maxEndingHere = arr[0];	
    for (int i = 1; i < size; i++) {	
        maxEndingHere = maxEndingHere + arr[i];	
        if (arr[i] > maxEndingHere) {	
            maxEndingHere = arr[i];	
            if (maxSoFar < maxEndingHere) {	
                start = i;	
            }	
        }	
        if (maxSoFar < maxEndingHere) {	
            maxSoFar = maxEndingHere;	
            end = i;	
        }	
    }	
    logger.info("Found Maximum Subarray between {} and {}", Math.min(start, end), end);	
    return maxSoFar;	
}

Here, we updated the start and end to find the maximum subarray indices.

Note that we take Math.min(start, end) instead of start as the start index of the maximum subarray. This is because, if the array contains only negative numbers, the maximum subarray would be the largest element itself. In this case, if (arr[i] > maxEndingHere) will always be true. That is, the value of start is greater than the value of end.

3.4. Complexity

Since we only need to iterate the array once, the time complexity of this algorithm is O(n).

So as we can see, the time taken by this solution grows linearly with the number of elements in the array. Consequently, it is more efficient than the brute force approach we discussed in the last section.

4. Conclusion

In this quick tutorial, we’ve described two ways to solve the maximum subarray problem.

First, we explored a brute force approach and saw that this iterative solution resulted in quadratic time. Later, we then discussed the Kadane algorithm and used dynamic programming to solve the problem in linear time.

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)