Start learning free

LESSON 260 OF 410 · HASH TABLE

Number of Distinct Values II in O(n) Time and O(n) Space using Java

Practice O(n) Read the full explanation

Given an array of integers, count how many distinct values exist in the array.

Example:

Input: [1, 5, -3, 1, -4, 2, -4, 7, 7]
Output: 6
Explanation: the distinct values in the array are [1, 5, -3, -4, 2, 7]

Note:

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


STEP 1 OF 6
    Ctrl + Enter to check

    JAVA · HASH TABLE

    Distinct Values in Java, explained

    Understanding the Problem

    The core challenge of this problem is to efficiently count the number of distinct values in an array. This is a common problem in data processing and analysis, where identifying unique elements is often required. A potential pitfall is using a naive approach that may not meet the time and space complexity requirements.

    Approach

    To solve this problem, we need to think about how to efficiently track unique elements. A naive solution might involve nested loops to compare each element with every other element, but this would result in O(n^2) time complexity, which is not optimal.

    Instead, we can use a HashSet, which allows for O(1) average time complexity for insertions and lookups. By iterating through the array once and adding each element to the HashSet, we can ensure that only unique elements are stored. The size of the HashSet at the end of the iteration will give us the count of distinct values.

    Algorithm

    1. Initialize an empty HashSet.
    2. Iterate through each element in the array.
    3. Add each element to the HashSet.
    4. After the iteration, the size of the HashSet will be the number of distinct values.

    Code Implementation

    import java.util.HashSet;
    
    public class DistinctValues {
        public static int countDistinctValues(int[] arr) {
            // Initialize a HashSet to store unique values
            HashSet<Integer> uniqueValues = new HashSet<>();
            
            // Iterate through the array and add each element to the HashSet
            for (int num : arr) {
                uniqueValues.add(num);
            }
            
            // The size of the HashSet is the number of distinct values
            return uniqueValues.size();
        }
    
        public static void main(String[] args) {
            int[] arr = {1, 5, -3, 1, -4, 2, -4, 7, 7};
            System.out.println("Number of distinct values: " + countDistinctValues(arr)); // Output: 6
        }
    }
    

    Complexity Analysis

    The time complexity of this approach is O(n) because we iterate through the array once. The space complexity is also O(n) because, in the worst case, all elements in the array are distinct, and we store all of them in the HashSet.

    Edge Cases

    Potential edge cases include:

    • An empty array: The output should be 0.
    • An array with all identical elements: The output should be 1.
    • An array with negative and positive integers: The algorithm should handle this correctly.

    Examples:

    Input: []
    Output: 0
    
    Input: [1, 1, 1, 1]
    Output: 1
    
    Input: [-1, -1, 2, 2]
    Output: 2
    

    Testing

    To test the solution comprehensively, consider a variety of test cases:

    • Simple cases with a few elements.
    • Cases with all distinct elements.
    • Cases with all identical elements.
    • Cases with a mix of negative and positive integers.

    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 data structures that can help achieve the desired time and space complexity.
    • Start with a simple solution and then optimize it.
    • Practice similar problems to improve problem-solving skills.

    Conclusion

    In this blog post, we discussed how to count the number of distinct values in an array efficiently using a HashSet in Java. 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:

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