Given an input stream of n integers, represented as an array arr[], and an integer k. After each insertion of an element into the stream, you need to determine the kth largest element so far (considering all elements including duplicates). If k elements have not yet been inserted, return -1 for that insertion. Return an array of size n containing the kth largest element after each insertion step.
Examples:
Input: arr[] = [1, 2, 3, 4, 5, 6], k = 4
Output: -1 -1 -1 1 2 3
Explanation: The first three insertions have fewer than 4 elements, so output is -1. From the fourth insertion onward, the kth largest elements are 1, 2, and 3 respectively.Input: arr[] = [10, 20, 5, 15], k = 2
Output: -1 10 10 15
Explanation: First insertion gives -1 as fewer than 2 elements. After second, 2nd largest is 10. Then still 10. After inserting 15, elements are [10, 20, 5, 15]; 2nd largest is now 15.Input: arr[] = [3, 4], k = 1
Output: 3 4
Explanation: After each insertion, there is at least 1 element, so the 1st largest elements are 3 and then 4.
Table of Content
[Naive Approach] Using Repeated Sorting - O(n*n*log(n)) Time and O(n) Space
The idea is to maintain a sorted array of all elements seen so far to easily access the kth smallest. We sort the array repeatedly after each insertion so that the elements are always in increasing order. This ensures that we can directly pick the kth smallest from a fixed index when we have at least k elements. If fewer than k elements are present, we return -1 since the kth smallest doesn't exist yet.
Dry run for arr[] = [1, 2, 3, 4, 5, 6], k = 4 :
- i=0, topK = [1], size < k so res = [-1]
- i=1, topK = [1,2], size < k so res = [-1,-1]
- i=2, topK = [1,2,3], size < k so res = [-1,-1,-1]
- i=3, topK = [1,2,3,4], pick topK[0] = 1 so res = [-1,-1,-1,1]
- i=4, topK = [1,2,3,4,5], pick topK[1] = 2 so res = [-1,-1,-1,1,2]
- i=5, topK = [1,2,3,4,5,6], pick topK[2] = 3 so res = [-1,-1,-1,1,2,3]
Final Output: [-1, -1, -1, 1, 2, 3]
#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;
vector<int> kthLargest(vector<int> &arr, int k)
{
vector<int> res;
vector<int> topK;
for (int i = 0; i < arr.size(); i++)
{
topK.push_back(arr[i]);
sort(topK.begin(), topK.end());
// If at least k elements are present, pick the
// kth smallest (0-based index: i - k + 1)
if (topK.size() >= k)
{
res.push_back(topK[i - k + 1]);
}
else
{
// Less than k elements so far, push -1
res.push_back(-1);
}
}
return res;
}
int main()
{
vector<int> arr = {1, 2, 3, 4, 5, 6};
int k = 4;
vector<int> res = kthLargest(arr, k);
for (int x : res)
{
cout << x << " ";
}
return 0;
}
import java.util.*;
class GfG {
public static ArrayList<Integer> kthLargest(int[] arr, int k)
{
ArrayList<Integer> res = new ArrayList<>();
ArrayList<Integer> topK = new ArrayList<>();
for (int i = 0; i < arr.length; i++) {
topK.add(arr[i]);
Collections.sort(topK);
// If at least k elements are present, pick the
// kth smallest (0-based index: i - k + 1)
if (topK.size() >= k) {
res.add(topK.get(i - k + 1));
}
else {
// Less than k elements so far, push -1
res.add(-1);
}
}
return res;
}
public static void main(String[] args)
{
int[] arr = { 1, 2, 3, 4, 5, 6 };
int k = 4;
ArrayList<Integer> res = kthLargest(arr, k);
for (int x : res) {
System.out.print(x + " ");
}
}
}
def kthLargest(arr, k):
res = []
topK = []
for i in range(len(arr)):
topK.append(arr[i])
topK.sort()
# If at least k elements are present, pick the
# kth smallest (0-based index: i - k + 1)
if len(topK) >= k:
res.append(topK[i - k + 1])
else:
# Less than k elements so far, push -1
res.append(-1)
return res
if __name__ == "__main__":
arr = [1, 2, 3, 4, 5, 6]
k = 4
res = kthLargest(arr, k)
for x in res:
print(x, end=" ")
using System;
using System.Collections.Generic;
class GfG {
public static List<int> kthLargest(int[] arr, int k)
{
List<int> res = new List<int>();
List<int> topK = new List<int>();
for (int i = 0; i < arr.Length; i++) {
topK.Add(arr[i]);
topK.Sort();
// If at least k elements are present, pick the
// kth smallest (0-based index: i - k + 1)
if (topK.Count >= k) {
res.Add(topK[i - k + 1]);
}
else {
// Less than k elements so far, push -1
res.Add(-1);
}
}
return res;
}
public static void Main()
{
int[] arr = { 1, 2, 3, 4, 5, 6 };
int k = 4;
List<int> res = kthLargest(arr, k);
foreach(int x in res) { Console.Write(x + " "); }
}
}
function kthLargest(arr, k)
{
let res = [];
let topK = [];
for (let i = 0; i < arr.length; i++) {
topK.push(arr[i]);
topK.sort((a, b) => a - b);
// If at least k elements are present, pick the
// kth smallest (0-based index: i - k + 1)
if (topK.length >= k) {
res.push(topK[i - k + 1]);
}
else {
// Less than k elements so far, push -1
res.push(-1);
}
}
return res;
}
// Driver Code
let arr = [ 1, 2, 3, 4, 5, 6 ];
let k = 4;
let res = kthLargest(arr, k);
let ans = "";
for (let x of res) {
ans += x + " ";
}
console.log(ans.trim());
Output
-1 -1 -1 1 2 3
[Expected Approach] Using Min Heap - O(n*log(k)) Time and O(k) Space
The idea is to use Min Heap to maintain the k largest elements seen so far in the heap. Since the smallest among these k is the kth largest overall, it is always at the top of the heap. For each new element, if it's larger than the smallest in the heap, we replace the top element to keep only the largest k elements.
Dry run for arr[] = [1, 2, 3, 4, 5, 6], k = 4 :
- i=0, heap = [1], size < k so res = [-1]
- i=1, heap = [1,2], size < k so res = [-1,-1]
- i=2, heap = [1,2,3], size < k so res = [-1,-1,-1]
- i=3, heap = [1,2,3,4], kth = 1 so res = [-1,-1,-1,1]
- i=4, pop(1), push(5), heap = [2,3,4,5], kth = 2 so res = [-1,-1,-1,1,2]
- i=5, pop(2), push(6), heap = [3,4,5,6], kth = 3 so res = [-1,-1,-1,1,2,3]
Final Output: [-1, -1, -1, 1, 2, 3]
#include <iostream>
#include <queue>
#include <vector>
using namespace std;
vector<int> kthLargest(vector<int>& arr, int k)
{
vector<int> res;
// Min Heap to store the k largest elements
priority_queue<int, vector<int>, greater<int>> minHeap;
for (int i = 0; i < arr.size(); i++)
{
// If heap has less than k elements,
// insert directly
if (minHeap.size() < k)
{
minHeap.push(arr[i]);
}
// If current element is larger
// than the smallest in heap,
// replace the smallest
else if (arr[i] > minHeap.top())
{
minHeap.pop();
minHeap.push(arr[i]);
}
// If heap has at least k elements,
// top of heap is the kth largest so far
if (minHeap.size() == k)
{
res.push_back(minHeap.top());
}
// Else, not enough elements
// to determine kth largest
else
{
res.push_back(-1);
}
}
return res;
}
int main()
{
vector<int> arr = {1, 2, 3, 4, 5, 6};
int k = 4;
vector<int> res = kthLargest(arr, k);
for (int x : res)
{
cout << x << " ";
}
return 0;
}
import java.util.*;
class GfG {
public static ArrayList<Integer> kthLargest(int[] arr,
int k)
{
ArrayList<Integer> res = new ArrayList<>();
// Min Heap to store the k largest elements
PriorityQueue<Integer> minHeap
= new PriorityQueue<>();
for (int i = 0; i < arr.length; i++) {
// If heap has less than k elements,
// insert directly
if (minHeap.size() < k) {
minHeap.add(arr[i]);
}
// If current element is larger
// than the smallest in heap,
// replace the smallest
else if (arr[i] > minHeap.peek()) {
minHeap.poll();
minHeap.add(arr[i]);
}
// If heap has at least k elements,
// top of heap is the kth largest so far
if (minHeap.size() == k) {
res.add(minHeap.peek());
}
// Else, not enough elements
// to determine kth largest
else {
res.add(-1);
}
}
return res;
}
public static void main(String[] args)
{
int[] arr = { 1, 2, 3, 4, 5, 6 };
int k = 4;
ArrayList<Integer> res = kthLargest(arr, k);
for (int x : res) {
System.out.print(x + " ");
}
}
}
import heapq
def kthLargest(arr, k):
res = []
# Min Heap to store the k largest elements
minHeap = []
for i in range(len(arr)):
# If heap has less than k elements,
# insert directly
if len(minHeap) < k:
heapq.heappush(minHeap, arr[i])
# If current element is larger
# than the smallest in heap,
# replace the smallest
elif arr[i] > minHeap[0]:
heapq.heappop(minHeap)
heapq.heappush(minHeap, arr[i])
# If heap has at least k elements,
# top of heap is the kth largest so far
if len(minHeap) == k:
res.append(minHeap[0])
# Else, not enough elements
# to determine kth largest
else:
res.append(-1)
return res
if __name__ == "__main__":
arr = [1, 2, 3, 4, 5, 6]
k = 4
res = kthLargest(arr, k)
for x in res:
print(x, end=" ")
using System;
using System.Collections.Generic;
class GfG {
public static List<int> kthLargest(int[] arr, int k)
{
List<int> res = new List<int>();
// List to simulate the Min Heap
List<int> minHeap = new List<int>();
for (int i = 0; i < arr.Length; i++) {
// If heap has less than k elements,
// insert directly
if (minHeap.Count < k) {
minHeap.Add(arr[i]);
minHeap.Sort();
}
// If current element is larger
// than the smallest in heap,
// replace the smallest
else if (arr[i] > minHeap[0]) {
minHeap.RemoveAt(0);
minHeap.Add(arr[i]);
minHeap.Sort();
}
// If heap has at least k elements,
// top of heap is the kth largest so far
if (minHeap.Count == k) {
res.Add(minHeap[0]);
}
// Else, not enough elements
// to determine kth largest
else {
res.Add(-1);
}
}
return res;
}
public static void Main()
{
int[] arr = { 1, 2, 3, 4, 5, 6 };
int k = 4;
List<int> res = kthLargest(arr, k);
foreach(int x in res) { Console.Write(x + " "); }
}
}
class MinHeap {
constructor() {
this.heap = [];
}
push(val) {
this.heap.push(val);
this.heap.sort((a, b) => a - b);
}
pop() {
return this.heap.shift();
}
peek() {
return this.heap[0];
}
size() {
return this.heap.length;
}
}
function kthLargest(arr, k) {
let res = [];
// Min Heap to store the k largest elements
let minHeap = new MinHeap();
for (let i = 0; i < arr.length; i++) {
// If heap has less than k elements,
// insert directly
if (minHeap.size() < k) {
minHeap.push(arr[i]);
}
// If current element is larger
// than the smallest in heap,
// replace the smallest
else if (arr[i] > minHeap.peek()) {
minHeap.pop();
minHeap.push(arr[i]);
}
// If heap has at least k elements,
// top of heap is the kth largest so far
if (minHeap.size() == k) {
res.push(minHeap.peek());
}
// Else, not enough elements
// to determine kth largest
else {
res.push(-1);
}
}
return res;
}
// Driver Code
let arr = [1, 2, 3, 4, 5, 6];
let k = 4;
let res = kthLargest(arr, k);
console.log(res.join(" "));
Output
-1 -1 -1 1 2 3