Start learning free

LESSON 275 OF 410 · BINARY SEARCH

Smallest K Integers V in O(n log maxVal) Time Complexity using Java

Practice O(n log n) Read the full explanation

Given an array of positive integers nums, return the smallest k values, in any order you want.

Example:

Input: nums = [5, 9, 3, 6, 2, 1, 3, 2, 7, 5], k = 4
Output: [1, 2, 2, 3]
Explanation: Smallest number is 1, 2nd smallest is 2, 
            3rd smallest is 2, 4th smallest is 3
The result can be in any order, [2, 1, 3, 2] is also a correct answer.

Note:

For this lesson, your algorithm should run in O(n log V) time, where V is the range of values in nums (from the smallest to the largest value).


STEP 1 OF 21
    Ctrl + Enter to check

    JAVA · BINARY SEARCH

    Smallest K in Java, explained

    Understanding the Problem

    The core challenge of this problem is to find the smallest k integers from an array of positive integers. This problem is significant in scenarios where we need to filter out the smallest elements from a large dataset, such as in data analysis or competitive programming.

    Potential pitfalls include misunderstanding the requirement to return the smallest k values in any order and not optimizing the solution to meet the time complexity constraint.

    Approach

    To solve this problem, we can consider several approaches:

    Naive Solution

    A naive solution would be to sort the array and then return the first k elements. However, this approach has a time complexity of O(n log n), which is not optimal for this problem.

    Optimized Solution

    We can use a min-heap (priority queue) to efficiently find the smallest k elements. The min-heap allows us to keep track of the smallest elements as we iterate through the array. This approach has a time complexity of O(n log k), which is better but still not optimal for the given constraints.

    Optimal Solution

    To achieve the required O(n log maxVal) time complexity, we can use a counting sort-like approach. This approach leverages the fact that the array contains positive integers, and we can use an array to count the occurrences of each integer. This method ensures we meet the time complexity constraint and uses O(1) extra space.

    Algorithm

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

    1. Find the maximum value in the array to determine the size of the counting array.
    2. Create a counting array to store the frequency of each integer in the input array.
    3. Iterate through the input array and populate the counting array.
    4. Iterate through the counting array to collect the smallest k integers.

    Code Implementation

    import java.util.*;
    
    public class SmallestKIntegers {
        public static List<Integer> findSmallestK(int[] nums, int k) {
            // Step 1: Find the maximum value in the array
            int maxVal = Arrays.stream(nums).max().getAsInt();
            
            // Step 2: Create a counting array
            int[] count = new int[maxVal + 1];
            
            // Step 3: Populate the counting array
            for (int num : nums) {
                count[num]++;
            }
            
            // Step 4: Collect the smallest k integers
            List<Integer> result = new ArrayList<>();
            for (int i = 0; i < count.length && result.size() < k; i++) {
                while (count[i] > 0 && result.size() < k) {
                    result.add(i);
                    count[i]--;
                }
            }
            
            return result;
        }
    
        public static void main(String[] args) {
            int[] nums = {5, 9, 3, 6, 2, 1, 3, 2, 7, 5};
            int k = 4;
            List<Integer> smallestK = findSmallestK(nums, k);
            System.out.println(smallestK);
        }
    }
    

    Complexity Analysis

    The time complexity of the optimal solution is O(n log maxVal) because we iterate through the input array to populate the counting array and then iterate through the counting array to collect the smallest k integers. The space complexity is O(1) extra space since the counting array size depends on the maximum value in the input array, not the input size.

    Edge Cases

    Potential edge cases include:

    • k is greater than the length of the array: The algorithm should handle this by returning all elements in the array.
    • All elements in the array are the same: The algorithm should correctly return k instances of that element.

    Testing

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

    • Simple cases with small arrays.
    • Arrays with duplicate elements.
    • Arrays where k is larger than the array length.
    • Arrays with all elements being the same.

    Thinking and Problem-Solving Tips

    When approaching such problems, consider the following tips:

    • Understand the problem constraints and requirements thoroughly.
    • Think about different approaches and their time and space complexities.
    • Optimize your solution step-by-step, starting from a naive approach.
    • Practice solving similar problems to improve your problem-solving skills.

    Conclusion

    In this blog post, we discussed how to find the smallest k integers from an array of positive integers. We explored different approaches, including a naive solution and an optimal solution using a counting sort-like approach. We also provided a detailed algorithm, code implementation, complexity analysis, and testing strategies. Understanding and solving such problems is crucial for improving your algorithmic thinking and coding skills.

    Additional Resources

    For further reading and practice, consider the following resources:

    • LeetCode - Practice coding problems and challenges.
    • GeeksforGeeks - Tutorials and articles on algorithms and data structures.
    • Coursera - Online courses on algorithms and computer science.
    Keep going with JavaAbout 340 step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free