Start learning free

LESSON 264 OF 410 · HASH TABLE

Longest Subarray with at most K Distinct Integers in Java (O(n^2) Time Complexity)

Practice O(n2) Read the full explanation

Given an array of integers, find the longest subarray that contains at most K distinct integers and return its length.

Example

Input: nums = [1, 2, 1, 2, 3], k = 2
Output: 4
Explanation: the subarray nums[0...3] contains 2 distinct values: [1, 2] and is the longest subarray

Note:

Your algorithm should run in at most O(n2) time and use O(n) extra space.


STEP 1 OF 8
    Ctrl + Enter to check

    JAVA · HASH TABLE

    Longest Subarray With At Most K Distinct Integers in Java, explained

    Problem Definition

    The problem requires finding the longest subarray within a given array of integers that contains at most K distinct integers. The output should be the length of this subarray.

    Input:

    • nums: An array of integers.
    • k: An integer representing the maximum number of distinct integers allowed in the subarray.

    Output:

    • An integer representing the length of the longest subarray with at most K distinct integers.

    Constraints:

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

    Example:

    Input: nums = [1, 2, 1, 2, 3], k = 2
    Output: 4
    Explanation: The subarray nums[0...3] contains 2 distinct values: [1, 2] and is the longest subarray.

    Understanding the Problem

    The core challenge is to find the longest contiguous subarray with at most K distinct integers. This problem is significant in scenarios where we need to analyze data streams or sequences with constraints on diversity.

    Common pitfalls include not handling edge cases where K is larger than the number of unique elements in the array or when the array is empty.

    Approach

    To solve this problem, we can use a sliding window approach combined with a hash map to keep track of the count of distinct integers within the current window.

    Naive Solution:

    A naive solution would involve checking all possible subarrays and counting the distinct integers in each, which would result in an O(n^3) time complexity. This is not optimal.

    Optimized Solution:

    We can optimize this using a sliding window approach:

    • Use two pointers to represent the current window.
    • Expand the window by moving the right pointer and include the current element in the count.
    • If the count of distinct integers exceeds K, move the left pointer to reduce the window size until the count is at most K.
    • Keep track of the maximum window size observed.

    Algorithm

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

    1. Initialize two pointers, left and right, to the start of the array.
    2. Use a hash map to keep track of the count of each integer in the current window.
    3. Expand the window by moving the right pointer and update the hash map.
    4. If the number of distinct integers exceeds K, move the left pointer to shrink the window until the count is at most K.
    5. Update the maximum length of the window observed.
    6. Continue until the right pointer reaches the end of the array.

    Code Implementation

    import java.util.HashMap;
    import java.util.Map;
    
    public class LongestSubarrayKDistinct {
        public int lengthOfLongestSubarrayKDistinct(int[] nums, int k) {
            if (nums == null || nums.length == 0 || k == 0) {
                return 0;
            }
    
            // HashMap to store the count of elements in the current window
            Map<Integer, Integer> map = new HashMap<>();
            int left = 0, right = 0, maxLength = 0;
    
            // Iterate through the array with the right pointer
            while (right < nums.length) {
                // Add the current element to the map
                map.put(nums[right], map.getOrDefault(nums[right], 0) + 1);
    
                // If the number of distinct elements exceeds k, shrink the window from the left
                while (map.size() > k) {
                    map.put(nums[left], map.get(nums[left]) - 1);
                    if (map.get(nums[left]) == 0) {
                        map.remove(nums[left]);
                    }
                    left++;
                }
    
                // Update the maximum length of the window
                maxLength = Math.max(maxLength, right - left + 1);
                right++;
            }
    
            return maxLength;
        }
    
        public static void main(String[] args) {
            LongestSubarrayKDistinct solution = new LongestSubarrayKDistinct();
            int[] nums = {1, 2, 1, 2, 3};
            int k = 2;
            System.out.println("Length of longest subarray: " + solution.lengthOfLongestSubarrayKDistinct(nums, k)); // Output: 4
        }
    }
    

    Complexity Analysis

    The time complexity of the sliding window approach is O(n) because each element is processed at most twice (once by the right pointer and once by the left pointer). The space complexity is O(n) due to the hash map used to store the count of elements.

    Edge Cases

    Consider the following edge cases:

    • Empty array: The output should be 0.
    • K is 0: The output should be 0.
    • K is larger than the number of unique elements in the array: The output should be the length of the entire array.

    Testing

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

    • Simple cases with small arrays and different values of K.
    • Edge cases such as empty arrays and arrays with all identical elements.
    • Large arrays to test the performance and efficiency of the algorithm.

    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 time and space complexities.
    • Use data structures like hash maps to keep track of counts and frequencies efficiently.
    • Practice similar problems to improve problem-solving skills and familiarity with common patterns.

    Conclusion

    In this blog post, we discussed how to find the longest subarray with at most K distinct 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 developing strong problem-solving skills in programming.

    Additional Resources

    For further reading and practice, consider the following resources:

    Keep going with JavaAbout 340 step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free