Find k largest elements in an array
Given an array arr[] and an integer k, the task is to find k largest elements in the given array. Elements in the output array should be in decreasing order.
Examples:
Input: [1, 23, 12, 9, 30, 2, 50], k = 3
Output: [50, 30, 23]Input: [11, 5, 12, 9, 44, 17, 2], k = 2
Output: [44, 17]
Table of Content
[Naive Approach] Using Sorting
The idea is to sort the input array in descending order, so the first k elements in the array will be the k largest elements.
// C++ program to find k largest elements in an
// array using sorting
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
vector<int> kLargest(vector<int> &arr, int k) {
// sort the given array in descending order
sort(arr.begin(), arr.end(), greater<int>());
// store the first k element in result array
vector<int> res(arr.begin(), arr.begin() + k);
return res;
}
int main() {
vector<int>arr = {1, 23, 12, 9, 30, 2, 50};
int k = 3;
vector<int> res = kLargest(arr, k);
for(int ele : res)
cout << ele << " ";
return 0;
}
// Java program to find k largest elements in an array using
// sorting
import java.util.*;
class GfG {
static ArrayList<Integer> kLargest(int[] arr, int k) {
int n = arr.length;
// Convert int type to Integer
// for sorting with a comparator
Integer[] arrInteger =
Arrays.stream(arr).boxed().toArray(Integer[]::new);
// Sort the array in descending order
Arrays.sort(arrInteger, Collections.reverseOrder());
// Store the first k elements in result list
ArrayList<Integer> res = new ArrayList<>();
for (int i = 0; i < k; i++)
res.add(arrInteger[i]);
return res;
}
public static void main(String[] args) {
int[] arr = {1, 23, 12, 9, 30, 2, 50};
int k = 3;
ArrayList<Integer> res = kLargest(arr, k);
for (int ele : res)
System.out.print(ele + " ");
}
}
# Python program to find k largest elements in an
# array using sorting
def kLargest(arr, k):
# sort the given array in descending order
arr.sort(reverse=True)
# store the first k elements in result list
res = arr[:k]
return res
if __name__ == "__main__":
arr = [1, 23, 12, 9, 30, 2, 50]
k = 3
res = kLargest(arr, k)
print(' '.join(map(str, res)))
// C# program to find k largest elements in an
// array using sorting
using System;
using System.Collections.Generic;
using System.Linq;
class GfG {
static List<int> kLargest(int[] arr, int k) {
// sort the given array in descending order
Array.Sort(arr, (a, b) => b.CompareTo(a));
// store the first k elements in result list
List<int> res = new List<int>();
for (int i = 0; i < k; i++) {
res.Add(arr[i]);
}
return res;
}
static void Main() {
int[] arr = {1, 23, 12, 9, 30, 2, 50};
int k = 3;
List<int> res = kLargest(arr, k);
foreach (int ele in res)
Console.Write(ele + " ");
}
}
// JavaScript program to find k largest elements
// in an array using sorting
function kLargest(arr, k) {
// sort the given array in descending order
arr.sort((a, b) => b - a);
// store the first k elements in result array
let res = arr.slice(0, k);
return res;
}
// Driver Code
const arr = [1, 23, 12, 9, 30, 2, 50];
const k = 3;
const res = kLargest(arr, k);
console.log(res.join(' '));
Output
50 30 23
Time complexity: O(n * log n)
Auxiliary Space: O(1)
[Expected Approach] Using Priority Queue(Min-Heap)
The idea is, as we iterate through the array, we keep track of the k largest elements at each step. To do this, we use a min-heap. First, we insert the initial k elements into the min-heap. After that, for each next element, we compare it with the top of the heap. Since the top element of the min-heap is the smallest among the k elements, if the current element is larger than the top, it means the top element is no longer one of the k largest elements. In this case, we remove the top and insert the larger element. After completing the entire traversal, the heap will contain exactly the k largest elements of the array.
// C++ program to find the k largest elements in the
// array using min heap
#include <iostream>
#include <vector>
#include <queue>
#include <algorithm>
using namespace std;
// Function to find the k largest elements in the array
vector<int> kLargest(vector<int> &arr, int k) {
// Min Priority Queue (Min-Heap) with first k
// elements of the array
priority_queue<int, vector<int>, greater<int>>
minH(arr.begin(), arr.begin() + k);
// Travers n - k elements
for (int i = k; i < arr.size(); i++) {
// If the top of heap is less than the arr[i]
// then remove top element and insert arr[i]
if(minH.top() < arr[i]) {
minH.pop();
minH.push(arr[i]);
}
}
vector<int> res;
// Min heap will contain only k
// largest element
while (!minH.empty()) {
res.push_back(minH.top());
minH.pop();
}
// Reverse the result array, so that all
// elements are in decreasing order
reverse(res.begin(), res.end());
return res;
}
int main() {
vector<int> arr = {1, 23, 12, 9, 30, 2, 50};
int k = 3;
vector<int> res = kLargest(arr, k);
for(int ele : res)
cout << ele << " ";
return 0;
}
// Java program to find the k largest elements in the
// array using min heap
import java.util.*;
class GfG {
// Function to find the k largest elements in the array
static ArrayList<Integer> kLargest(int[] arr, int k) {
// Min-heap to store the k largest elements
PriorityQueue<Integer> minHeap = new PriorityQueue<>(k);
// Add first k elements to the heap
for (int i = 0; i < k; i++) {
minHeap.add(arr[i]);
}
// Traverse the rest of the array
for (int i = k; i < arr.length; i++) {
// If current element is larger than
// the smallest in heap
if (arr[i] > minHeap.peek()) {
minHeap.poll();
minHeap.add(arr[i]);
}
}
// Extract elements from the heap
ArrayList<Integer> res = new ArrayList<>();
while (!minHeap.isEmpty()) {
res.add(minHeap.poll());
}
// Reverse the list for descending order
Collections.reverse(res);
return res;
}
public static void main(String[] args) {
int[] arr = {1, 23, 12, 9, 30, 2, 50};
int k = 3;
ArrayList<Integer> res = kLargest(arr, k);
for (int ele : res) {
System.out.print(ele + " ");
}
}
}
# Python program to find the k largest elements in the
# array using min heap
import heapq
# Function to find the k largest elements in the array
def kLargest(arr, k):
# Create a min-heap with the first k elements
minH = arr[:k]
heapq.heapify(minH)
# Traverse the rest of the array
for x in arr[k:]:
if x > minH[0]:
heapq.heapreplace(minH, x)
res = []
# Min heap will contain only k
# largest element
while minH:
res.append(heapq.heappop(minH))
# Reverse the result array, so that all
# elements are in decreasing order
res.reverse()
return res
if __name__ == "__main__":
arr = [1, 23, 12, 9, 30, 2, 50]
k = 3
res = kLargest(arr, k)
print(" ".join(map(str, res)))
// C# program to find the k largest elements in the
// array using min heap
using System;
using System.Collections.Generic;
class GfG {
// Function to find the k largest elements in the array
static List<int> kLargest(int[] arr, int k) {
// Min-heap using a SortedSet
SortedSet<int> minH = new SortedSet<int>();
// Insert the first k elements into the min-heap
for (int i = 0; i < k; i++) {
minH.Add(arr[i]);
}
// Process the remaining elements
for (int i = k; i < arr.Length; i++) {
// If the current element is larger
// than the smallest in the heap
if (arr[i] > minH.Min) {
minH.Remove(minH.Min);
minH.Add(arr[i]);
}
}
// Extract k largest elements from the heap
List<int> res = new List<int>(minH);
// Reverse the result array to get
// elements in decreasing order
res.Sort((a, b) => b.CompareTo(a));
return res;
}
static void Main() {
int[] arr = { 1, 23, 12, 9, 30, 2, 50 };
int k = 3;
List<int> res = kLargest(arr, k);
foreach (int ele in res)
Console.Write(ele + " ");
}
}
//Driver Code Starts
// JavaScript program to find the k largest elements in the
// array using min heap
class MinHeap {
constructor() {
this.heap = [];
}
// Swap two elements in the heap
swap(i, j) {
[this.heap[i], this.heap[j]] = [this.heap[j], this.heap[i]];
}
// Heapify up to maintain min heap property
heapifyUp() {
let index = this.heap.length - 1;
while (index > 0) {
let parentIndex = Math.floor((index - 1) / 2);
if (this.heap[parentIndex] <= this.heap[index]) break;
this.swap(parentIndex, index);
index = parentIndex;
}
}
// Heapify down to maintain min heap property
heapifyDown() {
let index = 0;
while (2 * index + 1 < this.heap.length) {
let leftChild = 2 * index + 1;
let rightChild = 2 * index + 2;
let smallest = leftChild;
if (rightChild < this.heap.length && this.heap[rightChild] < this.heap[leftChild]) {
smallest = rightChild;
}
if (this.heap[index] <= this.heap[smallest]) break;
this.swap(index, smallest);
index = smallest;
}
}
// Insert element into the min heap
push(val) {
this.heap.push(val);
this.heapifyUp();
}
// Remove and return the top element (smallest)
pop() {
if (this.heap.length === 1) return this.heap.pop();
let min = this.heap[0];
this.heap[0] = this.heap.pop();
this.heapifyDown();
return min;
}
// Get the top element (smallest)
top() {
return this.heap[0];
}
// Check if the heap is empty
empty() {
return this.heap.length === 0;
}
}
//Driver Code Ends
// Function to find the k largest elements in the array
function kLargest(arr, k) {
// Min Priority Queue (Min-Heap) with first k
// elements of the array
let minH = new MinHeap();
for (let i = 0; i < k; i++) {
minH.push(arr[i]);
}
// Traverse n - k elements
for (let i = k; i < arr.length; i++) {
// If the top of heap is less than the arr[i]
// then remove top element and insert arr[i]
if (minH.top() < arr[i]) {
minH.pop();
minH.push(arr[i]);
}
}
let res = [];
// Min heap will contain only k
// largest elements
while (!minH.empty()) {
res.push(minH.pop());
}
// Reverse the result array, so that all
// elements are in decreasing order
res.reverse();
return res;
}
//Driver Code Starts
// Driver Code
let arr = [1, 23, 12, 9, 30, 2, 50];
let k = 3;
let res = kLargest(arr, k);
console.log(res.join(" "));
//Driver Code Ends
Output
50 30 23
Time Complexity: O(n * log k), this solution can work in O(k + (n-k) Log K) as build heap take linear time.
Auxiliary Space: O(k)
Note: JavaScript does not seem to support min heap in native implementation, so it is recommended to use Quick Select implementation.
[Alternate Approach] Using Quick Select algorithm
The idea is to use the partitioning step of QuickSort to find the k largest elements in the array, without sorting the entire array. When sorting the element in the descending order, the partitioning step rearranges the elements in a way that all elements greater than or equal to a chosen pivot (usually the last element) are placed on its left, and all elements lesser than the pivot are on its right. And pivot element in its correct sorted position.
After each partition, we compare the number of elements in the leftpart of the array (which contains all elements greater than or equal to the pivot) with k:
- Number of elements in the left = k, it means all elements in the left part (including pivot) are the k largest elements.
- Number of elements in the left > k, it means that k largest elements exist in the left subarray only, so we recursively search in the left subarray.
- Number of elements in the left < k, it means that the k largest elements include the entire left part of the array along with some elements from the right part. Therefore we reduce k by the number of elements already covered on the left side and search in the right subarray.
// C++ program to find the k largest elements in the array
// using partitioning step of quick sort
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
// Function to partition the array around a pivot
int partition(vector<int> &arr, int left, int right) {
// Last element is chosen as a pivot.
int pivot = arr[right];
int i = left;
for (int j = left; j < right; j++) {
// Elements greater than or equal to pivot
// are placed in the left side of pivot
if (arr[j] >= pivot) {
swap(arr[i], arr[j]);
i++;
}
}
swap(arr[i], arr[right]);
// The correct sorted position of the pivot
return i;
}
void quickSelect(vector<int> &arr, int left, int right, int k) {
if (left <= right) {
int pivotIdx = partition(arr, left, right);
// Count of all elements in the left part
int leftCnt = pivotIdx - left + 1;
// If leftCnt is equal to k, then we have
// found the k largest element
if (leftCnt == k)
return;
// Search in the left subarray
if (leftCnt > k)
quickSelect(arr, left, pivotIdx - 1, k);
// Reduce the k by number of elements already covered
// and search in the right subarray
else
quickSelect(arr, pivotIdx + 1, right, k - leftCnt);
}
}
vector<int> kLargest(vector<int> &arr, int k) {
int n = arr.size();
quickSelect(arr, 0, n - 1, k);
// First k elements of the array will be the largest
vector<int> res(arr.begin(), arr.begin() + k);
// Sort the result in descending order
sort(res.begin(), res.end(), greater<int>());
return res;
}
int main() {
vector<int> arr = {1, 23, 12, 9, 30, 2, 50};
int k = 3;
vector<int> res = kLargest(arr, k);
for (int ele : res)
cout << ele << " ";
return 0;
}
// Java program to find the k largest elements in the array
// using partitioning step of quick sort
import java.util.*;
class GfG {
// Function to partition the array around a pivot
static int partition(int[] arr, int left, int right) {
// Last element is chosen as a pivot.
int pivot = arr[right];
int i = left;
for (int j = left; j < right; j++) {
// Elements greater than or equal to pivot
// are placed in the left side of pivot
if (arr[j] >= pivot) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
i++;
}
}
int temp = arr[i];
arr[i] = arr[right];
arr[right] = temp;
// The correct sorted position of the pivot
return i;
}
static void quickSelect(int[] arr, int left, int right, int k) {
if (left <= right) {
int pivotIdx = partition(arr, left, right);
// Count of all elements in the left part
int leftCnt = pivotIdx - left + 1;
// If leftCnt is equal to k, then we have
// found the k largest element
if (leftCnt == k)
return;
// Search in the left subarray
if (leftCnt > k)
quickSelect(arr, left, pivotIdx - 1, k);
// Reduce the k by number of elements already covered
// and search in the right subarray
else
quickSelect(arr, pivotIdx + 1, right, k - leftCnt);
}
}
static ArrayList<Integer> kLargest(int[] arr, int k) {
quickSelect(arr, 0, arr.length - 1, k);
ArrayList<Integer> res = new ArrayList<>();
// First k elements of the array, will be the largest
for(int i = 0; i < k; i++)
res.add(arr[i]);
// Sort the result in descending order
Collections.sort(res, Collections.reverseOrder());
return res;
}
public static void main(String[] args) {
int[] arr = {1, 23, 12, 9, 30, 2, 50};
int k = 3;
ArrayList<Integer> res = kLargest(arr, k);
for (int ele : res)
System.out.print(ele + " ");
}
}
# Python program to find the k largest elements in the array
# using partitioning step of quick sort
# Function to partition the array around a pivot
def partition(arr, left, right):
# Last element is chosen as a pivot.
pivot = arr[right]
i = left
for j in range(left, right):
# Elements greater than or equal to pivot
# are placed in the left side of pivot
if arr[j] >= pivot:
arr[i], arr[j] = arr[j], arr[i]
i += 1
arr[i], arr[right] = arr[right], arr[i]
# The correct sorted position of the pivot
return i
def quickSelect(arr, left, right, k):
if left <= right:
pivotIdx = partition(arr, left, right)
# Count of all elements in the left part
leftCnt = pivotIdx - left + 1
# If leftCnt is equal to k, then we have
# found the k largest element
if leftCnt == k:
return
# Search in the left subarray
if leftCnt > k:
quickSelect(arr, left, pivotIdx - 1, k)
# Reduce the k by number of elements already covered
# and search in the right subarray
else:
quickSelect(arr, pivotIdx + 1, right, k - leftCnt)
def kLargest(arr, k):
quickSelect(arr, 0, len(arr) - 1, k)
# First k elements of the array, will be the largest
res = arr[:k]
# Sort the result in descending order
res.sort(reverse=True)
return res
if __name__ == "__main__":
arr = [1, 23, 12, 9, 30, 2, 50]
k = 3
res = kLargest(arr, k)
print(" ".join(map(str, res)))
// C# program to find the k largest elements in the array
// using partitioning step of quick sort
using System;
using System.Collections.Generic;
class GfG {
// Function to partition the array around a pivot
static int partition(int[] arr, int left, int right) {
// Last element is chosen as a pivot.
int pivot = arr[right];
int i = left;
for (int j = left; j < right; j++) {
// Elements greater than or equal to pivot
// are placed in the left part of pivot
if (arr[j] >= pivot) {
swap(arr, i, j);
i++;
}
}
swap(arr, i, right);
// The correct sorted position of the pivot
return i;
}
static void quickSelect(int[] arr, int left, int right, int k) {
if (left <= right) {
int pivotIdx = partition(arr, left, right);
// Count of all elements in the left part
int leftCnt = pivotIdx - left + 1;
// If leftCnt is equal to k, then we have
// found the k largest element
if (leftCnt == k)
return;
// Search in the left subarray
if (leftCnt > k)
quickSelect(arr, left, pivotIdx - 1, k);
// Reduce the k by number of elements already covered
// and search in the right subarray
else
quickSelect(arr, pivotIdx + 1, right, k - leftCnt);
}
}
static List<int> kLargest(int[] arr, int k) {
quickSelect(arr, 0, arr.Length - 1, k);
// First k elements of the array will be the largest
List<int> res = new List<int>();
for (int i = 0; i < k; i++) {
res.Add(arr[i]);
}
// Sort the list in descending order
res.Sort((a, b) => b.CompareTo(a));
return res;
}
static void swap(int[] arr, int i, int j) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
static void Main() {
int[] arr = {1, 23, 12, 9, 30, 2, 50};
int k = 3;
List<int> res = kLargest(arr, k);
foreach (int ele in res)
Console.Write(ele + " ");
}
}
// JavaScript program to find the k largest elements in the array
// using partitioning step of quick sort
// Function to partition the array around a pivot
function partition(arr, left, right) {
// Last element is chosen as a pivot.
let pivot = arr[right];
let i = left;
for (let j = left; j < right; j++) {
// Elements greater than or equal to pivot are
// placed in the left part of pivot
if (arr[j] >= pivot) {
[arr[i], arr[j]] = [arr[j], arr[i]];
i++;
}
}
[arr[i], arr[right]] = [arr[right], arr[i]];
// The correct sorted position of the pivot
return i;
}
function quickSelect(arr, left, right, k) {
if (left <= right) {
let pivotIdx = partition(arr, left, right);
// Count of all elements in the left part
let leftCnt = pivotIdx - left + 1;
// If leftCnt is equal to k, then the first
// k element of the array will be largest
if (leftCnt === k)
return;
// Search in the left subarray
if (leftCnt > k)
quickSelect(arr, left, pivotIdx - 1, k);
// Reduce the k by number of elements already covered
// and search in the right subarray
else
quickSelect(arr, pivotIdx + 1, right, k - leftCnt);
}
}
function kLargest(arr, k) {
quickSelect(arr, 0, arr.length - 1, k);
// First k elements of the array, will be the largest
let res = arr.slice(0, k);
// Sort the first k elements in descending order
res.sort((a, b) => b - a);
return res;
}
// Driver Code
const arr = [1, 23, 12, 9, 30, 2, 50];
const k = 3;
const res = kLargest(arr, k);
console.log(res.join(' '));
Output
50 30 23
Time Complexity: O(n2) in worst case (O(n) on average).
Auxiliary Space: O(n)