Start learning free

LESSON 220 OF 410 · SORTING

Number of Distinct Values in O(n log n) Time Using Java

Practice O(n log 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:

For this lesson, your algorithm should run in O(n log n) time and use O(1) extra space.
(There are faster solutions which we will discuss in future lessons)


Hints:

Let's sort the array in non-decreasing order. In this way all the equal elements will come one after another.

Then, we can traverse the sorted array from left to right using an index i. We should increment the solution if the value at index i has not been seen before. How can we check this?

The value at index i has never been seen before if it is different from the value at index i - 1.

STEP 1 OF 5
    Ctrl + Enter to check

    JAVA · SORTING

    Distinct Values in Java, explained

    Problem Definition

    The task is to count the number of distinct values in a given array of integers.

    Input: An array of integers.

    Output: An integer representing the number of distinct values in the array.

    Constraints:

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

    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]

    Understanding the Problem

    The core challenge is to identify and count unique elements in the array efficiently. This problem is significant in various applications such as data analysis, where understanding the diversity of data points is crucial.

    Potential pitfalls include not handling duplicate values correctly or using more space than allowed.

    Approach

    To solve this problem, we can use the following approach:

    1. Sort the array in non-decreasing order. This ensures that duplicate values are adjacent to each other.
    2. Traverse the sorted array and count the number of unique values by comparing each element with the previous one.

    Let's discuss why this approach works:

    • Sorting the array takes O(n log n) time.
    • Traversing the array takes O(n) time.
    • We use O(1) extra space since we only need a few variables to keep track of the count and the previous value.

    Algorithm

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

    1. Sort the array in non-decreasing order.
    2. Initialize a counter to 1 (since the first element is always unique).
    3. Iterate through the array starting from the second element.
    4. For each element, compare it with the previous element. If they are different, increment the counter.
    5. Return the counter as the number of distinct values.

    Code Implementation

    import java.util.Arrays;
    
    public class DistinctValues {
        public static int countDistinct(int[] nums) {
            // Step 1: Sort the array
            Arrays.sort(nums);
            
            // Step 2: Initialize the count of distinct values
            int count = 1; // The first element is always unique
            
            // Step 3: Traverse the sorted array
            for (int i = 1; i < nums.length; i++) {
                // Step 4: Check if the current element is different from the previous one
                if (nums[i] != nums[i - 1]) {
                    count++;
                }
            }
            
            // Step 5: Return the count of distinct values
            return count;
        }
    
        public static void main(String[] args) {
            int[] nums = {1, 5, -3, 1, -4, 2, -4, 7, 7};
            System.out.println("Number of distinct values: " + countDistinct(nums)); // Output: 6
        }
    }
    

    Complexity Analysis

    Time Complexity: The sorting step takes O(n log n) time, and the traversal step takes O(n) time. Therefore, the overall time complexity is O(n log n).

    Space Complexity: The algorithm uses O(1) extra space since we only need a few variables for counting and comparison.

    Edge Cases

    Consider the following edge cases:

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

    Examples:

    Input: []
    Output: 0
    
    Input: [2, 2, 2, 2]
    Output: 1
    
    Input: [1, 2, 3, 4, 5]
    Output: 5
    

    Testing

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

    • Simple cases with a few elements.
    • Cases with negative and positive integers.
    • Edge cases as discussed above.

    Example test cases:

    public static void main(String[] args) {
        // Test case 1: Simple case
        int[] nums1 = {1, 5, -3, 1, -4, 2, -4, 7, 7};
        System.out.println("Number of distinct values: " + countDistinct(nums1)); // Output: 6
    
        // Test case 2: Empty array
        int[] nums2 = {};
        System.out.println("Number of distinct values: " + countDistinct(nums2)); // Output: 0
    
        // Test case 3: All identical elements
        int[] nums3 = {2, 2, 2, 2};
        System.out.println("Number of distinct values: " + countDistinct(nums3)); // Output: 1
    
        // Test case 4: All distinct elements
        int[] nums4 = {1, 2, 3, 4, 5};
        System.out.println("Number of distinct values: " + countDistinct(nums4)); // Output: 5
    }
    

    Thinking and Problem-Solving Tips

    Here are some tips to approach and think about such problems:

    • Understand the problem requirements and constraints thoroughly.
    • Break down the problem into smaller steps and solve each step methodically.
    • Consider different approaches and analyze their time and space complexities.
    • Practice solving 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 using an efficient algorithm with O(n log n) time complexity and O(1) extra space. 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.

    Keep practicing and exploring further to enhance your understanding and proficiency in algorithms and data structures.

    Additional Resources

    For further reading and practice, consider the following resources:

    • LeetCode - A platform for practicing coding problems.
    • GeeksforGeeks - A comprehensive resource for learning algorithms and data structures.
    • Coursera - Online courses on algorithms and data structures.
    Keep going with JavaAbout 340 step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free