Given an array arr[] of positive integers and an integer k, The task is to return k largest elements in decreasing order.
Examples:
Input: arr[] = [12, 5, 787, 1, 23], k = 2
Output: [787, 23]
Explanation: 1st largest element in the array is 787 and second largest is 23.Input: arr[] = [1, 23, 12, 9, 30, 2, 50], k = 3
Output: [50, 30, 23]
Explanation: Three Largest elements in the array are 50, 30 and 23.Input: arr[] = [12, 23], k = 1
Output: [23]
Explanation: 1st Largest element in the array is 23.
Table of Content
[Naive Approach] Sorting - O(n log n) Time and O(1) Space
The idea is to sort the array in decreasing order and return the first k elements, which are the largest elements in the array.
Working of Approach:
- Sort the array in decreasing order.
- Create an empty result array to store the answer.
- Traverse the first k elements of the sorted array.
- Add these elements to the result array.
- Return the result array containing the k largest elements.
#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;
vector<int> kLargest(vector<int> &arr, int k)
{
// Sort the array in decreasing order
sort(arr.begin(), arr.end(), greater<int>());
vector<int> res;
// Store the first k largest elements
for (int i = 0; i < k; i++)
{
res.push_back(arr[i]);
}
// Return the k largest elements
return res;
}
int main()
{
vector<int> arr = {12, 5, 787, 1, 23};
int k = 2;
vector<int> ans = kLargest(arr, k);
cout << "[";
for (int i = 0; i < ans.size(); i++)
{
cout << ans[i];
if (i < ans.size() - 1)
cout << ", ";
}
cout << "]";
return 0;
}
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
public class GFG {
public static ArrayList<Integer> kLargest(int[] arr,
int k)
{
// Sort the array in decreasing order
Integer[] arrInteger
= Arrays.stream(arr).boxed().toArray(
Integer[] ::new);
Arrays.sort(arrInteger, Collections.reverseOrder());
ArrayList<Integer> res = new ArrayList<>();
// Store the first k largest elements
for (int i = 0; i < k; i++) {
res.add(arrInteger[i]);
}
// Return the k largest elements
return res;
}
public static void main(String[] args)
{
int[] arr = { 12, 5, 787, 1, 23 };
int k = 2;
ArrayList<Integer> ans = kLargest(arr, k);
System.out.println(ans);
}
}
def kLargest(arr, k):
# Sort the array in decreasing order
arr.sort(reverse=True)
res = []
# Store the first k largest elements
for i in range(k):
res.append(arr[i])
# Return the k largest elements
return res
if __name__ == '__main__':
arr = [12, 5, 787, 1, 23]
k = 2
ans = kLargest(arr, k)
print('[', end='')
for i in range(len(ans)):
print(ans[i], end='')
if i < len(ans) - 1:
print(', ', end='')
print(']')
using System;
using System.Collections.Generic;
using System.Linq;
public class GFG {
public static List<int> kLargest(int[] arr, int k)
{
// Sort the array in decreasing order
Array.Sort(arr);
Array.Reverse(arr);
List<int> res = new List<int>();
// Store the first k largest elements
for (int i = 0; i < k; i++) {
res.Add(arr[i]);
}
// Return the k largest elements
return res;
}
public static void Main()
{
int[] arr = { 12, 5, 787, 1, 23 };
int k = 2;
List<int> ans = kLargest(arr, k);
Console.Write("[");
for (int i = 0; i < ans.Count; i++) {
Console.Write(ans[i]);
if (i < ans.Count - 1)
Console.Write(", ");
}
Console.Write("]");
}
}
function kLargest(arr, k)
{
// Sort the array in decreasing order
arr.sort((a, b) => b - a);
let res = [];
// Store the first k largest elements
for (let i = 0; i < k; i++) {
res.push(arr[i]);
}
// Return the k largest elements
return res;
}
// Driver Code
let arr = [ 12, 5, 787, 1, 23 ];
let k = 2;
let ans = kLargest(arr, k);
console.log("[");
for (let i = 0; i < ans.length; i++) {
process.stdout.write(ans[i].toString());
if (i < ans.length - 1)
process.stdout.write(", ");
}
console.log("]");
Output
[787, 23]
[Expected Approach] Min-Heap - O(n log k) Time and O(k) Space
The idea is to maintain a min-heap of size k containing the k largest elements. If a new element is greater than the smallest element in the heap, replace the smallest element with it.
Working of Approach:
- Create a min-heap to store the k largest elements.
- Insert the first k elements into the heap.
- Traverse the remaining elements and compare each with the smallest element at the heap's top.
- If the current element is larger, remove the smallest element and insert the current element.
- Extract all elements from the heap, reverse the result, and return it.
Let us understand with an example:
- Insert 12 and 5 into the min-heap. The heap contains [5, 12].
- Process 787. Since 787 > 5, remove 5 and insert 787. The heap contains [12, 787].
- Process 1. Since 1 < 12, ignore it.
- Process 23. Since 23 > 12, remove 12 and insert 23. The heap contains [23, 787].
- Extract the elements and reverse the result to get [787, 23].
Output: [787, 23].
#include <algorithm>
#include <iostream>
#include <queue>
#include <vector>
using namespace std;
vector<int> kLargest(vector<int> &arr, int k)
{
int n = arr.size();
// Min-heap to store the k largest elements
priority_queue<int, vector<int>, greater<int>> pq;
// Traverse the array
for (int i = 0; i < n; i++)
{
// If the heap already contains k elements
if (pq.size() == k)
{
// Replace the smallest element if the current element is larger
if (pq.top() < arr[i])
{
pq.pop();
pq.push(arr[i]);
}
}
else
{
// Insert elements until the heap contains k elements
pq.push(arr[i]);
}
}
vector<int> res;
// Extract elements from the min-heap
while (!pq.empty())
{
res.push_back(pq.top());
pq.pop();
}
// Reverse the result to get decreasing order
reverse(res.begin(), res.end());
// Return the k largest elements
return res;
}
int main()
{
vector<int> arr = {12, 5, 787, 1, 23};
int k = 2;
vector<int> ans = kLargest(arr, k);
cout << "[";
for (int i = 0; i < ans.size(); i++)
{
cout << ans[i];
if (i < ans.size() - 1)
cout << ", ";
}
cout << "]";
return 0;
}
import java.util.ArrayList;
import java.util.Collections;
import java.util.PriorityQueue;
public class GFG {
public static ArrayList<Integer> kLargest(int[] arr,
int k)
{
int n = arr.length;
// Min-heap to store the k largest elements
PriorityQueue<Integer> pq = new PriorityQueue<>();
// Traverse the array
for (int i = 0; i < n; i++) {
// If the heap already contains k elements
if (pq.size() == k) {
// Replace the smallest element if the
// current element is larger
if (pq.peek() < arr[i]) {
pq.poll();
pq.add(arr[i]);
}
}
else {
// Insert elements until the heap contains k
// elements
pq.add(arr[i]);
}
}
ArrayList<Integer> res = new ArrayList<>();
// Extract elements from the min-heap
while (!pq.isEmpty()) {
res.add(pq.poll());
}
// Reverse the result to get decreasing order
Collections.reverse(res);
// Return the k largest elements
return res;
}
public static void main(String[] args)
{
int[] arr = { 12, 5, 787, 1, 23 };
int k = 2;
ArrayList<Integer> ans = kLargest(arr, k);
System.out.println(ans);
}
}
import heapq
def kLargest(arr, k):
n = len(arr)
# Min-heap to store the k largest elements
pq = []
# Traverse the array
for i in range(n):
# If the heap already contains k elements
if len(pq) == k:
# Replace the smallest element if the current element is larger
if pq[0] < arr[i]:
heapq.heappop(pq)
heapq.heappush(pq, arr[i])
else:
# Insert elements until the heap contains k elements
heapq.heappush(pq, arr[i])
res = []
# Extract elements from the min-heap
while pq:
res.append(heapq.heappop(pq))
# Reverse the result to get decreasing order
res.reverse()
# Return the k largest elements
return res
if __name__ == '__main__':
arr = [12, 5, 787, 1, 23]
k = 2
ans = kLargest(arr, k)
print('[', end='')
for i in range(len(ans)):
print(ans[i], end='')
if i < len(ans) - 1:
print(', ', end='')
print(']')
using System;
using System.Collections.Generic;
public class GFG {
public static List<int> kLargest(List<int> arr, int k)
{
int n = arr.Count;
// Min-heap to store the k largest elements
SortedSet<int> pq = new SortedSet<int>();
// Traverse the array
for (int i = 0; i < n; i++) {
// If the heap already contains k elements
if (pq.Count == k) {
// Replace the smallest element if the
// current element is larger
if (pq.Min < arr[i]) {
pq.Remove(pq.Min);
pq.Add(arr[i]);
}
}
else {
// Insert elements until the heap contains k
// elements
pq.Add(arr[i]);
}
}
List<int> res = new List<int>();
// Extract elements from the min-heap
foreach(int x in pq) { res.Add(x); }
// Reverse the result to get decreasing order
res.Reverse();
// Return the k largest elements
return res;
}
public static void Main()
{
List<int> arr = new List<int>{ 12, 5, 787, 1, 23 };
int k = 2;
List<int> ans = kLargest(arr, k);
Console.Write("[");
for (int i = 0; i < ans.Count; i++) {
Console.Write(ans[i]);
if (i < ans.Count - 1)
Console.Write(", ");
}
Console.Write("]");
}
}
function getParent(i) { return Math.floor((i - 1) / 2); }
function getLeft(i) { return 2 * i + 1; }
function getRight(i) { return 2 * i + 2; }
function swap(heap, i, j)
{
[heap[i], heap[j]] = [ heap[j], heap[i] ];
}
function shiftDown(heap, i)
{
let n = heap.length;
while (true) {
let largest = i;
let left = getLeft(i);
let right = getRight(i);
if (left < n && heap[left] > heap[largest]) {
largest = left;
}
if (right < n && heap[right] > heap[largest]) {
largest = right;
}
if (largest === i) {
break;
}
swap(heap, i, largest);
i = largest;
}
}
function heapify(heap)
{
for (let i = Math.floor(heap.length / 2) - 1; i >= 0;
i--) {
shiftDown(heap, i);
}
}
function removeMax(heap)
{
let max = heap[0];
heap[0] = heap[heap.length - 1];
heap.pop();
if (heap.length > 0) {
shiftDown(heap, 0);
}
return max;
}
function kLargest(arr, k)
{
let heap = [...arr ];
// Build a max-heap
heapify(heap);
let res = [];
// Extract the k largest elements
for (let i = 0; i < k; i++) {
res.push(removeMax(heap));
}
return res;
}
// Driver code
let arr = [ 12, 5, 787, 1, 23 ];
let k = 2;
console.log(kLargest(arr, k));
Output
[787, 23]
Note: JavaScript does not provide a built-in min-heap data structure. Therefore, Quick Select can be used as an alternative to find the k largest elements without implementing a min-heap.
[Alternate Approach] Quick Select - O(n ^ 2) Time and O(log n) Space
The idea is to use the partitioning step of QuickSort to find the k largest elements without sorting the entire array. During partitioning in descending order, all elements greater than or equal to the pivot are placed on its left, while smaller elements are placed on its right. The pivot is placed at its correct position.
After each partition, compare the number of elements in the left part, including the pivot, with k:
- If the number of elements on the left is equal to k, the left part contains the k largest elements.
- If the number of elements on the left is greater than k, search in the left subarray.
- If the number of elements on the left is less than k, include the entire left part and search in the right subarray for the remaining largest elements.
#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;
// Partition the array around the pivot
int partition(vector<int> &arr, int low, int high)
{
int pivot = arr[high];
int i = low;
// Place elements smaller than or equal to the pivot first
for (int j = low; j < high; j++)
{
if (arr[j] <= pivot)
{
swap(arr[i], arr[j]);
i++;
}
}
// Place the pivot at its correct position
swap(arr[i], arr[high]);
return i;
}
// Find the element at the required index using Quick Select
void quickSelect(vector<int> &arr, int low, int high, int target)
{
if (low >= high)
return;
// Partition the array and get the pivot position
int pivotIndex = partition(arr, low, high);
// Continue only in the part containing the target index
if (pivotIndex == target)
return;
else if (pivotIndex < target)
quickSelect(arr, pivotIndex + 1, high, target);
else
quickSelect(arr, low, pivotIndex - 1, target);
}
vector<int> kLargest(vector<int> &arr, int k)
{
int n = arr.size();
// Find the position separating the k largest elements
int target = n - k;
// Place the k largest elements in the last k positions
quickSelect(arr, 0, n - 1, target);
vector<int> res;
// Store the k largest elements
for (int i = target; i < n; i++)
{
res.push_back(arr[i]);
}
// Sort the selected elements in decreasing order
sort(res.begin(), res.end(), greater<int>());
// Return the k largest elements
return res;
}
int main()
{
vector<int> arr = {12, 5, 787, 1, 23};
int k = 2;
vector<int> ans = kLargest(arr, k);
cout << "[";
for (int i = 0; i < ans.size(); i++)
{
cout << ans[i];
if (i < ans.size() - 1)
cout << ", ";
}
cout << "]";
return 0;
}
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
public class GFG {
// Partition the array around the pivot
static int partition(int[] arr, int low, int high)
{
int pivot = arr[high];
int i = low;
// Place elements smaller than or equal to the pivot
// first
for (int j = low; j < high; j++) {
if (arr[j] <= pivot) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
i++;
}
}
// Place the pivot at its correct position
int temp = arr[i];
arr[i] = arr[high];
arr[high] = temp;
return i;
}
// Find the element at the required index using Quick
// Select
static void quickSelect(int[] arr, int low, int high,
int target)
{
if (low >= high)
return;
// Partition the array and get the pivot position
int pivotIndex = partition(arr, low, high);
// Continue only in the part containing the target
// index
if (pivotIndex == target)
return;
else if (pivotIndex < target)
quickSelect(arr, pivotIndex + 1, high, target);
else
quickSelect(arr, low, pivotIndex - 1, target);
}
static ArrayList<Integer> kLargest(int[] arr, int k)
{
int n = arr.length;
// Find the position separating the k largest
// elements
int target = n - k;
// Place the k largest elements in the last k
// positions
quickSelect(arr, 0, n - 1, target);
ArrayList<Integer> res = new ArrayList<>();
// Store the k largest elements
for (int i = target; i < n; i++) {
res.add(arr[i]);
}
// Sort the selected elements in decreasing order
res.sort(Collections.reverseOrder());
// Return the k largest elements
return res;
}
public static void main(String[] args)
{
int[] arr = { 12, 5, 787, 1, 23 };
int k = 2;
ArrayList<Integer> ans = kLargest(arr, k);
System.out.println(ans);
}
}
from typing import List
# Partition the array around the pivot
def partition(arr: List[int], low: int, high: int) -> int:
pivot = arr[high]
i = low
# Place elements smaller than or equal to the pivot first
for j in range(low, high):
if arr[j] <= pivot:
arr[i], arr[j] = arr[j], arr[i]
i += 1
# Place the pivot at its correct position
arr[i], arr[high] = arr[high], arr[i]
return i
# Find the element at the required index using Quick Select
def quickSelect(arr: List[int], low: int, high: int, target: int) -> None:
if low >= high:
return
# Partition the array and get the pivot position
pivotIndex = partition(arr, low, high)
# Continue only in the part containing the target index
if pivotIndex == target:
return
elif pivotIndex < target:
quickSelect(arr, pivotIndex + 1, high, target)
else:
quickSelect(arr, low, pivotIndex - 1, target)
def kLargest(arr: List[int], k: int) -> List[int]:
n = len(arr)
# Find the position separating the k largest elements
target = n - k
# Place the k largest elements in the last k positions
quickSelect(arr, 0, n - 1, target)
res = []
# Store the k largest elements
for i in range(target, n):
res.append(arr[i])
# Sort the selected elements in decreasing order
res.sort(reverse=True)
# Return the k largest elements
return res
if __name__ == "__main__":
arr = [12, 5, 787, 1, 23]
k = 2
ans = kLargest(arr, k)
print(ans)
using System;
using System.Collections.Generic;
public class GFG {
// Partition the array around the pivot
static int partition(int[] arr, int low, int high)
{
int pivot = arr[high];
int i = low;
// Place elements smaller than or equal to the pivot
// first
for (int j = low; j < high; j++) {
if (arr[j] <= pivot) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
i++;
}
}
// Place the pivot at its correct position
int temp2 = arr[i];
arr[i] = arr[high];
arr[high] = temp2;
return i;
}
// Find the element at the required index using Quick
// Select
static void quickSelect(int[] arr, int low, int high,
int target)
{
if (low >= high)
return;
// Partition the array and get the pivot position
int pivotIndex = partition(arr, low, high);
// Continue only in the part containing the target
// index
if (pivotIndex == target)
return;
else if (pivotIndex < target)
quickSelect(arr, pivotIndex + 1, high, target);
else
quickSelect(arr, low, pivotIndex - 1, target);
}
static List<int> kLargest(int[] arr, int k)
{
int n = arr.Length;
// Find the position separating the k largest
// elements
int target = n - k;
// Place the k largest elements in the last k
// positions
quickSelect(arr, 0, n - 1, target);
List<int> res = new List<int>();
// Store the k largest elements
for (int i = target; i < n; i++) {
res.Add(arr[i]);
}
// Sort the selected elements in decreasing order
res.Sort((a, b) => b.CompareTo(a));
// Return the k largest elements
return res;
}
public static void Main(string[] args)
{
int[] arr = { 12, 5, 787, 1, 23 };
int k = 2;
List<int> ans = kLargest(arr, k);
Console.WriteLine("[" + string.Join(", ", ans)
+ "]");
}
}
// Partition the array around the pivot
function partition(arr, low, high)
{
let pivot = arr[high];
let i = low;
// Place elements smaller than or equal to the pivot
// first
for (let j = low; j < high; j++) {
if (arr[j] <= pivot) {
[arr[i], arr[j]] = [ arr[j], arr[i] ];
i++;
}
}
// Place the pivot at its correct position
[arr[i], arr[high]] = [ arr[high], arr[i] ];
return i;
}
// Find the element at the required index using Quick Select
function quickSelect(arr, low, high, target)
{
if (low >= high) {
return;
}
// Partition the array and get the pivot position
let pivotIndex = partition(arr, low, high);
// Continue only in the part containing the target index
if (pivotIndex === target) {
return;
}
else if (pivotIndex < target) {
quickSelect(arr, pivotIndex + 1, high, target);
}
else {
quickSelect(arr, low, pivotIndex - 1, target);
}
}
function kLargest(arr, k)
{
let n = arr.length;
// Find the position separating the k largest elements
let target = n - k;
// Place the k largest elements in the last k positions
quickSelect(arr, 0, n - 1, target);
let res = [];
// Store the k largest elements
for (let i = target; i < n; i++) {
res.push(arr[i]);
}
// Sort the selected elements in decreasing order
res.sort((a, b) => b - a);
// Return the k largest elements
return res;
}
// Driver code
let arr = [ 12, 5, 787, 1, 23 ];
let k = 2;
let ans = kLargest(arr, k);
console.log(ans);
Output
[787, 23]