Longest Subarray Without Repeating IV in O(n) Time and O(n) Space using Java


Given an input array of integers, find the length of the longest subarray without repeating integers.

Example

Input: nums = [2, 5, 6, 2, 3, 1, 5, 6]
Output: 5
Explanation: [5, 6, 2, 3, 1] or [6, 2, 3, 1, 5] are both valid and of maximum length 5

Note:

For this lesson, your algorithm should run in O(n) time and use O(n) extra space


Problem Definition

The problem requires finding the length of the longest subarray in a given array of integers where no integer repeats. The input is an array of integers, and the output is a single integer representing the length of the longest subarray without repeating integers.

Input

  • An array of integers nums.

Output

  • An integer representing the length of the longest subarray without repeating integers.

Constraints and Assumptions

  • The algorithm should run in O(n) time.
  • The algorithm should use O(n) extra space.

Example

Input: nums = [2, 5, 6, 2, 3, 1, 5, 6]
Output: 5
Explanation: [5, 6, 2, 3, 1] or [6, 2, 3, 1, 5] are both valid and of maximum length 5

Understanding the Problem

The core challenge is to identify the longest contiguous subarray where all elements are unique. This problem is significant in various applications such as data stream processing, substring problems in strings, and more. A common pitfall is not handling the sliding window correctly, which can lead to incorrect results or inefficient solutions.

Approach

To solve this problem, we can use the sliding window technique combined with a hash set to keep track of the elements in the current window. The sliding window will help us maintain the subarray, and the hash set will ensure all elements are unique.

Naive Solution

A naive solution would involve checking all possible subarrays and verifying if they contain unique elements. This approach is not optimal as it has a time complexity of O(n^2) or worse, which is not suitable for large inputs.

Optimized Solution

The optimized solution uses the sliding window technique:

  • Initialize two pointers, start and end, both set to the beginning of the array.
  • Use a hash set to keep track of the unique elements in the current window.
  • Expand the window by moving the end pointer and add elements to the hash set.
  • If a duplicate is found, move the start pointer to the right until the duplicate is removed from the window.
  • Keep track of the maximum length of the window during this process.

Algorithm

Here is a step-by-step breakdown of the algorithm:

  1. Initialize start and end pointers to 0.
  2. Initialize an empty hash set to store unique elements.
  3. Initialize a variable maxLength to keep track of the maximum length of the subarray.
  4. Iterate through the array using the end pointer.
  5. If the element at end is not in the hash set, add it and update maxLength.
  6. If the element at end is in the hash set, remove elements from the hash set starting from start until the duplicate is removed.
  7. Continue this process until the end pointer reaches the end of the array.

Code Implementation

import java.util.HashSet;

public class LongestSubarrayWithoutRepeating {
    public static int lengthOfLongestSubarray(int[] nums) {
        // Initialize the start pointer, maxLength, and a hash set to store unique elements
        int start = 0, maxLength = 0;
        HashSet<Integer> set = new HashSet<>();

        // Iterate through the array using the end pointer
        for (int end = 0; end < nums.length; end++) {
            // If the element at end is already in the set, remove elements from the start
            while (set.contains(nums[end])) {
                set.remove(nums[start]);
                start++;
            }
            // Add the current element to the set
            set.add(nums[end]);
            // Update the maxLength
            maxLength = Math.max(maxLength, end - start + 1);
        }
        return maxLength;
    }

    public static void main(String[] args) {
        int[] nums = {2, 5, 6, 2, 3, 1, 5, 6};
        System.out.println("Length of the longest subarray without repeating integers: " + lengthOfLongestSubarray(nums));
    }
}

Complexity Analysis

The time complexity of this approach is O(n) because each element is processed at most twice (once by the end pointer and once by the start pointer). The space complexity is O(n) due to the hash set used to store unique elements.

Edge Cases

Potential edge cases include:

  • An empty array: The output should be 0.
  • An array with all unique elements: The output should be the length of the array.
  • An array with all identical elements: The output should be 1.

These edge cases can be tested to ensure the algorithm handles them correctly.

Testing

To test the solution comprehensively, consider the following test cases:

  • Simple cases with small arrays.
  • Arrays with all unique elements.
  • Arrays with all identical elements.
  • Large arrays to test performance.

Using a testing framework like JUnit can help automate and manage these tests effectively.

Thinking and Problem-Solving Tips

When approaching such problems, consider the following tips:

  • Understand the problem requirements and constraints thoroughly.
  • Think about different approaches and their trade-offs.
  • Use diagrams or pseudo-code to visualize the solution.
  • Practice similar problems to improve problem-solving skills.

Conclusion

In this blog post, we discussed how to find the length of the longest subarray without repeating integers using an optimized approach with a sliding window and hash set. We covered the problem definition, approach, algorithm, code implementation, complexity analysis, edge cases, and testing. Understanding and solving such problems is crucial for improving algorithmic thinking and coding skills.

Additional Resources

For further reading and practice, consider the following resources: