Start learning free

LESSON 312 OF 410 · HEAP

Smallest K Integers II in JavaScript (O(n log k) Time Complexity)

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


STEP 1 OF 9
    Ctrl + Enter to check

    JAVASCRIPT · HEAP

    Smallest K in JavaScript, explained

    Understanding the Problem

    The core challenge of this problem is to efficiently 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, statistics, and 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 O(n log k) time complexity constraint.

    Approach

    To solve this problem, we can use a max-heap (priority queue) to keep track of the smallest k elements. The idea is to maintain a heap of size k. As we iterate through the array, we add elements to the heap. If the heap exceeds size k, we remove the largest element (root of the max-heap). This ensures that the heap always contains the k smallest elements.

    Here's a step-by-step breakdown of the approach:

    1. Initialize a max-heap.
    2. Iterate through each element in the array.
    3. Add the current element to the heap.
    4. If the heap size exceeds k, remove the largest element from the heap.
    5. After processing all elements, the heap contains the k smallest elements.

    Algorithm

    Let's break down the algorithm in detail:

    1. Create a max-heap using a priority queue.
    2. For each element in the array:
      • Add the element to the heap.
      • If the heap size exceeds k, remove the largest element from the heap.
    3. Convert the heap to an array and return it.

    Code Implementation

    // Importing the priority queue library
    const { MaxPriorityQueue } = require('@datastructures-js/priority-queue');
    
    /**
     * Function to find the smallest k integers in an array
     * @param {number[]} nums - Array of positive integers
     * @param {number} k - Number of smallest integers to find
     * @return {number[]} - Array of k smallest integers
     */
    function smallestKIntegers(nums, k) {
      // Initialize a max-heap with a capacity of k
      const maxHeap = new MaxPriorityQueue({ priority: x => x });
    
      // Iterate through each element in the array
      for (const num of nums) {
        // Add the current element to the heap
        maxHeap.enqueue(num);
    
        // If the heap size exceeds k, remove the largest element
        if (maxHeap.size() > k) {
          maxHeap.dequeue();
        }
      }
    
      // Convert the heap to an array and return it
      return maxHeap.toArray().map(item => item.element);
    }
    
    // Example usage
    const nums = [5, 9, 3, 6, 2, 1, 3, 2, 7, 5];
    const k = 4;
    console.log(smallestKIntegers(nums, k)); // Output: [1, 2, 2, 3]
    

    Complexity Analysis

    The time complexity of this approach is O(n log k) because we perform log k operations for each of the n elements in the array. The space complexity is O(k) because the heap stores at most k elements.

    Edge Cases

    Consider the following edge cases:

    • k is 0: The output should be an empty array.
    • k is greater than the length of the array: The output should be the entire array sorted.
    • All elements in the array are the same: The output should be an array of k elements, all the same.

    Testing

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

    • Simple case: nums = [5, 9, 3, 6, 2, 1, 3, 2, 7, 5], k = 4
    • Edge case: nums = [1, 1, 1, 1], k = 2
    • Edge case: nums = [1, 2, 3], k = 0
    • Edge case: nums = [1, 2, 3], k = 5

    Thinking and Problem-Solving Tips

    When approaching such problems, consider the following tips:

    • Understand the problem constraints and requirements thoroughly.
    • Think about different data structures and their properties (e.g., heaps for efficient retrieval of smallest/largest elements).
    • Break down the problem into smaller steps and solve each step incrementally.
    • Practice similar problems to improve problem-solving skills and familiarity with different algorithms.

    Conclusion

    In this blog post, we discussed how to find the smallest k integers from an array of positive integers using a max-heap. 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 technical interviews.

    Additional Resources

    For further reading and practice, consider the following resources:

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