Longest Subarray Without Repeating II in Python (O(n^2) Time Complexity)


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^2) time and use O(n) extra space.
(There exist faster solutions which we will discuss in future lessons)


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:

nums = [2, 5, 6, 2, 3, 1, 5, 6]

Output:

5

Constraints and Assumptions:

  • The array can contain both positive and negative integers.
  • The array can be of any length, including zero.

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 to overlook the need for contiguous subarrays and mistakenly consider non-contiguous subarrays.

Approach

To solve this problem, we can use a sliding window approach. The naive solution involves checking all possible subarrays, which is not optimal. Instead, we can use a set to keep track of the elements in the current window and adjust the window size dynamically to ensure all elements are unique.

Naive Solution:

The naive solution involves generating all possible subarrays and checking each one for uniqueness. This approach has a time complexity of O(n^3) and is not efficient for large arrays.

Optimized Solution:

We can optimize the solution using a sliding window technique with a set to track unique elements. This approach ensures a time complexity of O(n^2) and uses O(n) extra space.

Algorithm

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

  1. Initialize two pointers, start and end, both set to the beginning of the array.
  2. Use a set to keep track of unique elements in the current window.
  3. Iterate through the array with the end pointer, adding elements to the set.
  4. If a duplicate is found, move the start pointer to the right until the duplicate is removed from the set.
  5. Update the maximum length of the subarray whenever a longer subarray is found.
  6. Continue until the end pointer reaches the end of the array.

Code Implementation

def longest_subarray_without_repeating(nums):
    # Initialize pointers and the set to track unique elements
    start = 0
    max_length = 0
    unique_elements = set()
    
    for end in range(len(nums)):
        # If the element is already in the set, remove elements from the start
        while nums[end] in unique_elements:
            unique_elements.remove(nums[start])
            start += 1
        
        # Add the current element to the set
        unique_elements.add(nums[end])
        
        # Update the maximum length
        max_length = max(max_length, end - start + 1)
    
    return max_length

# Example usage
nums = [2, 5, 6, 2, 3, 1, 5, 6]
print(longest_subarray_without_repeating(nums))  # Output: 5

Complexity Analysis

The time complexity of this approach is O(n^2) because, in the worst case, we might need to remove and add elements to the set multiple times. The space complexity is O(n) due to the extra space used by the set.

Edge Cases

Consider the following edge cases:

  • An empty array should return 0.
  • An array with all unique elements should return the length of the array.
  • An array with all identical elements should return 1.

Examples:

Input: nums = []
Output: 0

Input: nums = [1, 2, 3, 4, 5]
Output: 5

Input: nums = [1, 1, 1, 1]
Output: 1

Testing

To test the solution comprehensively, consider a variety of test cases, including simple, complex, and edge cases. Use testing frameworks like unittest or pytest for structured testing.

Thinking and Problem-Solving Tips

When approaching such problems, consider the following tips:

  • Break down the problem into smaller parts and understand each part.
  • Think about different approaches and their trade-offs.
  • 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 a sliding window approach. We covered the problem definition, approach, algorithm, code implementation, complexity analysis, edge cases, and testing. Understanding and solving such problems is crucial for improving problem-solving skills and preparing for coding interviews.

Additional Resources

For further reading and practice, consider the following resources: