Open In App

Average of max K numbers in a stream

Given a list of N numbers, and an integer ‘K’. The task is to print the average of max ‘K’ numbers after each query where a query consists of an integer element that needs to be added to the list of elements. 

Note: The queries are defined with an integer array ‘q’ 

Examples:

Input: N = 4, K = 3, arr = {1, 2, 3, 4}, q = {7, 2, 1, 5} 

Output: 4.666666 4.666666 4.666666 5.333333 
After query 1, arr = {1, 2, 3, 4, 7} and 
the average of max K (i.e. {3, 4, 7}) elements is 4.666666.
After query 2, arr = {1, 2, 3, 4, 7, 2} and 
the average is 4.666666 for {3, 4, 7}. 
After query 3, arr = {1, 2, 3, 4, 7, 2, 1} and 
the average is 4.666666 for {3, 4, 7}. 
After query 4, arr = {1, 2, 3, 4, 7, 2, 5} and 
the average is 5.333333 for {4, 5, 7}. 
Input: N = 5, K = 4, arr = {1, 2, 2, 3, 3}, q = {2, 5, 1} 
Output: 2.5 3.25 3.25

Approach:

Heap (Min Heap) data structure can be used to solve problems like these where insertion and deletions of the elements can be performed in O(log n) time.

Below is the implementation of the above approach: 




#include <bits/stdc++.h>
using namespace std;
 
void max_average_k_numbers(int n, int k, int m, int arr[],
                           int query[])
{
    double max_avg = 0.0;
 
    // min-heap to maintain the max k elements at any point
    // of time
    priority_queue<int, vector<int>, greater<int> > pq;
 
    // Sort the array in ascending order
    sort(arr, arr + n);
 
    // add max k elements to the heap
    double sum = 0;
    for (int i = n - 1; i >= n - k; i--) {
        pq.push(arr[i]);
        sum = sum + arr[i];
    }
 
    // perform offline queries
    for (int i = 0; i < m; i++) {
        // if the minimum element in the heap is less than
        // the incoming element
        if (query[i] > pq.top()) {
            int polled = pq.top();
            pq.pop();
            pq.push(query[i]);
 
            // decrement the current sum by the polled
            // element
            sum = sum - polled;
 
            // increment sum by the incoming element
            sum = sum + query[i];
        }
 
        // compute the average
        max_avg = sum / (double)k;
        cout << max_avg << endl;
    }
}
 
int main()
{
    int n = 4;
    int k = 3;
    int m = 4;
    int arr[] = { 1, 2, 3, 4 };
    int query[] = { 7, 2, 1, 5 };
 
    max_average_k_numbers(n, k, m, arr, query);
    return 0;
}




// Java implementation of the approach
import java.util.*;
 
class GFG {
 
    // Function that returns the
    // average of max k elements in
    // the list after each query
    static void max_average_k_numbers(int n,
                                    int k,
                                    int m,
                                    int[] arr,
                                    int[] query)
    {
        double max_avg = 0.0;
 
        // min-heap to maintain
        // the max k elements at
        // any point of time;
        PriorityQueue<Integer> pq = new PriorityQueue<Integer>();
 
        // Sort the array
        // in ascending order
        Arrays.sort(arr);
 
        // add max k elements
        // to the heap
        double sum = 0;
        for (int i = n - 1; i >= n - k; i--) {
            pq.add(arr[i]);
            sum = sum + arr[i];
        }
 
        // perform offline queries
        for (int i = 0; i < m; i++) {
 
            // if the minimum element in
            // the heap is less than
            // the incoming element
            if (query[i] > pq.peek()) {
                int polled = pq.poll();
                pq.add(query[i]);
 
                // decrement the current
                // sum by the polled element
                sum = sum - polled;
 
                // increment sum by the
                // incoming element
                sum = sum + query[i];
            }
 
            // compute the average
            max_avg = sum / (double)k;
            System.out.println(max_avg);
        }
    }
 
    // Driver code
    public static void main(String[] args)
    {
        int n = 4;
        int k = 3;
        int m = 4;
        int[] arr = new int[] { 1, 2, 3, 4 };
        int[] query = new int[] { 7, 2, 1, 5 };
 
        max_average_k_numbers(n, k, m, arr, query);
    }
}




# implementation of the approach
# importing heapq module
import heapq
 
# Function that returns the
# average of max k elements in
# the list after each query
def max_average_k_numbers(n, k, m, arr, query):
    max_avg = 0.0
     
    # min-heap to maintain
    # the max k elements at
    # any point of time
    pq = []
    Sum = 0
     
    # Sort the array in ascending order
    arr.sort()
     
    # add max k elements to heap pq
    for i in range(n - 1, n - k - 1, -1):
        pq.append(arr[i])
        Sum += arr[i]
         
    # heapify the heap pq for maintaining the
    # heap property
    heapq.heapify(pq)
     
    # perform offline queries
    for i in range(m):
       
        # if the minimum element in
        # the heap is less than
         # the incoming element
        if query[i] > pq[0]:
            polled = pq[0]
            pq[0] = pq[-1]
            pq.pop()
             
            # heapq.heapify(pq)
            pq.append(query[i])
             
            # decrement the current
            # sum by the polled element
            Sum -= polled
             
            # increment sum by the
            # incoming element
            Sum += query[i]
             
            # Again maintaining the heap property
            heapq.heapify(pq)
             
        # compute the average
        max_avg = Sum/float(k)
        print(max_avg)
 
 
# Driver Code
if __name__ == '__main__':
    n = 4
    k = 3
    m = 4
    arr = [1, 2, 3, 4]
    query = [7, 2, 1, 5]
    max_average_k_numbers(n, k, m, arr, query)
 
'''This Code is written By RAJAT KUMAR'''




using System;
using System.Collections.Generic;
using System.Linq;
 
public class MaxAverageKNumbers
{
  public static void Calculate(int n, int k, int m, int[] arr, int[] query)
  {
    double maxAvg = 0.0;
 
    // min-heap to maintain the max k elements at any point
    // of time
    var pq = new SortedSet<int>();
 
    // Sort the array in ascending order
    Array.Sort(arr);
 
    // add max k elements to the heap
    double sum = 0;
    for (int i = n - 1; i >= n - k; i--)
    {
      pq.Add(arr[i]);
      sum += arr[i];
    }
 
    // perform offline queries
    for (int i = 0; i < m; i++)
    {
      // if the minimum element in the heap is less than
      // the incoming element
      if (query[i] > pq.Min)
      {
        int polled = pq.Min;
        pq.Remove(polled);
        pq.Add(query[i]);
 
        // decrement the current sum by the polled
        // element
        sum -= polled;
 
        // increment sum by the incoming element
        sum += query[i];
      }
 
      // compute the average
      maxAvg = sum / (double)k;
      Console.WriteLine(maxAvg);
    }
  }
 
  public static void Main()
  {
    int n = 4;
    int k = 3;
    int m = 4;
    int[] arr = { 1, 2, 3, 4 };
    int[] query = { 7, 2, 1, 5 };
 
    MaxAverageKNumbers.Calculate(n, k, m, arr, query);
  }
}




function max_average_k_numbers(n, k, m, arr, query) {
  let max_avg = 0.0;
 
  // min-heap to maintain the max k elements at any point of time
  const pq = new PriorityQueue();
 
  // Sort the array in ascending order
  arr.sort((a, b) => a - b);
 
  // add max k elements to the heap
  let sum = 0;
  for (let i = n - 1; i >= n - k; i--) {
    pq.push(arr[i]);
    sum += arr[i];
  }
 
  // perform offline queries
  for (let i = 0; i < m; i++) {
    // if the minimum element in the heap is less than
    // the incoming element
    if (query[i] > pq.top()) {
      const polled = pq.top();
      pq.pop();
      pq.push(query[i]);
 
      // decrement the current sum by the polled element
      sum -= polled;
 
      // increment sum by the incoming element
      sum += query[i];
    }
 
    // compute the average
    max_avg = sum / k;
    console.log(max_avg);
  }
}
 
class PriorityQueue {
  constructor() {
    this.heap = [];
  }
 
  push(val) {
    this.heap.push(val);
    this.bubbleUp(this.heap.length - 1);
  }
 
  pop() {
    const last = this.heap.pop();
    const popped = this.heap[0];
    if (this.heap.length > 0) {
      this.heap[0] = last;
      this.bubbleDown(0);
    }
    return popped;
  }
 
  top() {
    return this.heap[0];
  }
 
  bubbleUp(idx) {
    const parent = Math.floor((idx - 1) / 2);
    if (parent >= 0 && this.heap[idx] < this.heap[parent]) {
      [this.heap[idx], this.heap[parent]] = [this.heap[parent], this.heap[idx]];
      this.bubbleUp(parent);
    }
  }
 
  bubbleDown(idx) {
    const left = 2 * idx + 1;
    const right = 2 * idx + 2;
    let smallest = idx;
    if (left < this.heap.length && this.heap[left] < this.heap[smallest]) {
      smallest = left;
    }
    if (right < this.heap.length && this.heap[right] < this.heap[smallest]) {
      smallest = right;
    }
    if (smallest !== idx) {
      [this.heap[idx], this.heap[smallest]] = [this.heap[smallest], this.heap[idx]];
      this.bubbleDown(smallest);
    }
  }
}
 
// Driver Code
const n = 4;
const k = 3;
const m = 4;
const arr = [1, 2, 3, 4];
const query = [7, 2, 1, 5];
max_average_k_numbers(n, k, m, arr, query);
 
// Contributed by sdeadityasharma

Output
4.666666666666667
4.666666666666667
4.666666666666667
5.333333333333333

Complexity Analysis:


Article Tags :