K-th Largest Sum Contiguous Subarray
Last Updated :
08 May, 2025
Given an array arr[] of size n, the task is to find the kth largest sum of contiguous subarray within the array of numbers that has both negative and positive numbers.
Examples:
Input: arr[] = [20, -5, -1], k = 3
Output: 14
Explanation: All sum of contiguous subarrays are (20, 15, 14, -5, -6, -1), so the 3rd largest sum is 14.
Input: arr[] = [10, -10, 20, -40], k = 6
Output: -10
Explanation: The 6th largest sum among sum of all contiguous subarrays is -10.
[Naive Approach - 1] Using Sorting - O(n2 * log n) Time and O(n ^ 2) Space
The idea is to calculate the Kth largest sum of contiguous subarrays by generating all possible contiguous subarray sums, storing them, and then sorting them in decreasing order to directly access the Kth largest. However, this approach can lead to memory issues when the input array size is large, as the number of contiguous subarrays grows quadratically with the size of the input array.
Step-by-Step Implementation:
- Traverse the input array using two nested loops to generate all contiguous subarrays.
- For each subarray, calculate the sum and store it in a list.
- After generating all subarray sums, sort the list in descending order.
- Return the element at the (k - 1)th index from the sorted list as the Kth largest sum.
C++
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
// Function to calculate Kth largest element
// in contiguous subarray sum
int kthLargest(vector<int> &arr, int k) {
int n = arr.size();
// to store all subarray sums
vector<int> sums;
// Generate all subarrays
for (int i = 0; i < n; i++) {
int sum = 0;
for (int j = i; j < n; j++) {
sum += arr[j];
sums.push_back(sum);
}
}
// Sort in decreasing order
sort(sums.begin(), sums.end(), greater<int>());
// return the Kth largest sum
return sums[k - 1];
}
int main() {
vector<int> arr = {20, -5, -1};\
int k = 3;
cout << kthLargest(arr, k);
return 0;
}
Java
import java.util.*;
class GfG {
// Function to calculate Kth largest element
// in contiguous subarray sum
public static int kthLargest(int[] arr, int k) {
int n = arr.length;
// to store all subarray sums
ArrayList<Integer> sums = new ArrayList<>();
// Generate all subarrays
for (int i = 0; i < n; i++) {
int sum = 0;
for (int j = i; j < n; j++) {
sum += arr[j];
sums.add(sum);
}
}
// Sort in decreasing order
Collections.sort(sums, Collections.reverseOrder());
// return the Kth largest sum
return sums.get(k - 1);
}
public static void main(String[] args) {
int[] arr = {20, -5, -1};
int k = 3;
System.out.println(kthLargest(arr, k));
}
}
Python
# Function to calculate Kth largest element
# in contiguous subarray sum
def kthLargest(arr, k):
n = len(arr)
# to store all subarray sums
sums = []
# Generate all subarrays
for i in range(n):
sum = 0
for j in range(i, n):
sum += arr[j]
sums.append(sum)
# Sort in decreasing order
sums.sort(reverse=True)
# return the Kth largest sum
return sums[k - 1]
if __name__ == "__main__":
arr = [20, -5, -1]
k = 3
print(kthLargest(arr, k))
C#
using System;
using System.Collections.Generic;
class GfG {
// Function to calculate Kth largest element
// in contiguous subarray sum
public static int kthLargest(int[] arr, int k) {
int n = arr.Length;
// to store all subarray sums
List<int> sums = new List<int>();
// Generate all subarrays
for (int i = 0; i < n; i++) {
int sum = 0;
for (int j = i; j < n; j++) {
sum += arr[j];
sums.Add(sum);
}
}
// Sort in decreasing order
sums.Sort((a, b) => b.CompareTo(a));
// return the Kth largest sum
return sums[k - 1];
}
public static void Main() {
int[] arr = {20, -5, -1};
int k = 3;
Console.WriteLine(kthLargest(arr, k));
}
}
JavaScript
// Function to calculate Kth largest element
// in contiguous subarray sum
function kthLargest(arr, k) {
let n = arr.length;
// to store all subarray sums
let sums = [];
// Generate all subarrays
for (let i = 0; i < n; i++) {
let sum = 0;
for (let j = i; j < n; j++) {
sum += arr[j];
sums.push(sum);
}
}
// Sort in decreasing order
sums.sort((a, b) => b - a);
// return the Kth largest sum
return sums[k - 1];
}
let arr = [20, -5, -1];
let k = 3;
console.log(kthLargest(arr, k));
[Naive Approach - 2] Using Prefix Sum and Sorting - O(n2 * log n) Time and O(n ^ 2) Space
The idea is to leverage a prefix-sum array to compute every contiguous subarray sum in constant time per pair of endpoints, collect all those sums into a single list, sort that list in descending order, and then directly pick out the Kth largest value.
Step-by-Step Implementation:
- Build a prefix-sum array
prefixSum
of length n+1
where prefixSum[i]
equals the total of the first i
elements. - Initialize an empty list to hold all subarray sums.
- For each start index
i
from 1 to n
, and for each end index j
from i
to n
, compute the subarray sum as prefixSum[j] – prefixSum[i–1]
and append it to the list. - Sort the list of subarray sums in decreasing order.
- Return the element at index
k–1
in the sorted list as the Kth largest sum.
C++
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
// The main function to find the K-th largest sum of
// contiguous subarray using Prefix Sum and Sorting
// approach.
int kthLargest(vector<int>& arr, int k) {
int n = arr.size();
// Create a prefix sum array.
vector<int> prefixSum(n + 1);
prefixSum[0] = 0;
for (int i = 1; i <= n; i++) {
prefixSum[i] = prefixSum[i - 1] + arr[i - 1];
}
// Create a vector to store all possible subarray sums.
vector<int> subarraySums;
for (int i = 0; i <= n; i++) {
for (int j = i + 1; j <= n; j++) {
subarraySums.push_back(prefixSum[j] - prefixSum[i]);
}
}
// Sort the subarray sums in decreasing order.
sort(subarraySums.begin(), subarraySums.end(),
greater<int>());
// Return the K-th largest sum of contiguous subarray.
return subarraySums[k - 1];
}
int main() {
vector<int> arr = {20, -5, -1};
int k = 3;
cout << kthLargest(arr, k);
return 0;
}
Java
import java.util.ArrayList;
import java.util.Collections;
class GfG {
// The main function to find the K-th largest sum of
// contiguous subarray using Prefix Sum and Sorting approach.
static int kthLargest(int[] arr, int k) {
int n = arr.length;
// Create a prefix sum array.
int[] prefixSum = new int[n + 1];
prefixSum[0] = 0;
for (int i = 1; i <= n; i++) {
prefixSum[i] = prefixSum[i - 1] + arr[i - 1];
}
// Create a list to store all possible subarray sums.
ArrayList<Integer> subarraySums = new ArrayList<>();
for (int i = 0; i <= n; i++) {
for (int j = i + 1; j <= n; j++) {
subarraySums.add(prefixSum[j] - prefixSum[i]);
}
}
// Sort the subarray sums in decreasing order.
Collections.sort(subarraySums, Collections.reverseOrder());
// Return the K-th largest sum of contiguous subarray.
return subarraySums.get(k - 1);
}
// Driver Code
public static void main(String[] args) {
int[] arr = {20, -5, -1};
int k = 3;
System.out.println(kthLargest(arr, k));
}
}
Python
# Python code to implement Prefix sum approach
import heapq
# The main function to find the K-th largest sum of
# contiguous subarray using Prefix Sum and Sorting
# approach.
def kthLargest(arr, k):
n = len(arr)
# Create a prefix sum array.
prefixSum = [0] * (n + 1)
for i in range(1, n+1):
prefixSum[i] = prefixSum[i - 1] + arr[i - 1]
# Create a heap to store K largest subarray sums.
subarraySums = []
heapq.heapify(subarraySums)
for i in range(n + 1):
for j in range(i + 1, n + 1):
subarraySum = prefixSum[j] - prefixSum[i]
if len(subarraySums) < k:
heapq.heappush(subarraySums, subarraySum)
else:
if subarraySum > subarraySums[0]:
heapq.heapreplace(subarraySums, subarraySum)
# Return the K-th largest sum of contiguous subarray.
return subarraySums[0]
# Driver Code
if __name__ == '__main__':
arr = [20, -5, -1]
k = 3
print(kthLargest(arr, k))
C#
using System;
using System.Collections.Generic;
using System.Linq;
class GfG{
// The main function to find the K-th largest sum of
// contiguous subarray using Prefix Sum and Sorting
// approach.
static int kthLargest(List<int> arr, int k){
int n = arr.Count;
// Create a prefix sum array.
List<int> prefixSum = new List<int>(n + 1);
prefixSum.Add(0);
for (int i = 1; i <= n; i++){
prefixSum.Add(prefixSum[i - 1] + arr[i - 1]);
}
// Create a list to store all possible subarray sums.
List<int> subarraySums = new List<int>();
for (int i = 0; i <= n; i++){
for (int j = i + 1; j <= n; j++){
subarraySums.Add(prefixSum[j] - prefixSum[i]);
}
}
// Sort the subarray sums in decreasing order.
subarraySums.Sort();
subarraySums.Reverse();
// Return the K-th largest sum of contiguous subarray.
return subarraySums[k - 1];
}
// Driver Code to test above function
public static void Main(string[] args){
List<int> arr = new List<int> { 20, -5, -1 };
int k = 3;
Console.WriteLine(kthLargest(arr, k)); // expected output is -10
}
}
JavaScript
// JavaScript code to implement Prefix sum approach
// The main function to find the K-th largest sum of
// contiguous subarray using Prefix Sum and Sorting
// approach.
function kthLargest(arr, k) {
let n = arr.length;
// Create a prefix sum array.
let prefixSum = new Array(n + 1).fill(0);
prefixSum[0] = 0;
for (let i = 1; i <= n; i++) {
prefixSum[i] = prefixSum[i - 1] + arr[i - 1];
}
// Create an array to store all possible subarray sums.
let subarraySums = [];
for (let i = 0; i <= n; i++) {
for (let j = i + 1; j <= n; j++) {
subarraySums.push(prefixSum[j] - prefixSum[i]);
}
}
// Sort the subarray sums in decreasing order.
subarraySums.sort((a, b) => b - a);
// Return the K-th largest sum of contiguous subarray.
return subarraySums[k - 1];
}
// Driver Code
let arr = [20, -5, -1];
let k = 3;
console.log(kthLargest(arr, k));
[Expected Approach] - Using Min Heap - O(n2 * log k) Time and O(k) Space
The key idea is to store the pre-sum of the array in a sum[] array. One can find the sum of contiguous subarray from index i to j as sum[j] - sum[i-1]. After this step, this problem becomes same as k-th smallest element in an array. So we generate all possible contiguous subarray sums and push them into the Min-Heap only if the size of Min-Heap is less than K or the current sum is greater than the root of the Min-Heap. In the end, the root of the Min-Heap is the required answer.
Follow the given steps to solve the problem using the above approach:
- Create a prefix sum array of the input array
- Create a Min-Heap that stores the subarray sum
- Iterate over the given array using the variable i such that 1 <= i <= N, here i denotes the starting point of the subarray
- Create a nested loop inside this loop using a variable j such that i <= j <= N, here j denotes the ending point of the subarray
- Calculate the sum of the current subarray represented by i and j, using the prefix sum array
- If the size of the Min-Heap is less than K, then push this sum into the heap
- Otherwise, if the current sum is greater than the root of the Min-Heap, then pop out the root and push the current sum into the Min-Heap
- Now the root of the Min-Heap denotes the Kth largest sum, Return it
C++
#include <iostream>
#include <vector>
#include <queue>
using namespace std;
// Function to calculate Kth largest element
// in contiguous subarray sum
int kthLargest(vector<int> &arr, int k) {
int n = arr.size();
// array to store prefix sums
vector<int> sum(n + 1);
sum[0] = 0;
sum[1] = arr[0];
for (int i = 2; i <= n; i++)
sum[i] = sum[i - 1] + arr[i - 1];
// min heap
priority_queue<int, vector<int>, greater<int>> pq;
// loop to calculate the contiguous subarray
// sums position-wise
for (int i = 1; i <= n; i++) {
// loop to traverse all positions that
// form contiguous subarray
for (int j = i; j <= n; j++) {
// calculates the contiguous subarray
// sums from j to i index
int x = sum[j] - sum[i - 1];
// if queue has less than k elements,
// then simply push it
if (pq.size() < k)
pq.push(x);
else {
// it the min heap has equal to
// k elements then just check
// if the largest kth element is
// smaller than x then insert
// else its of no use
if (pq.top() < x) {
pq.pop();
pq.push(x);
}
}
}
}
// the top element will be then kth
// largest element
return pq.top();
}
int main() {
vector<int> arr = {20, -5, -1};
int k = 3;
cout << kthLargest(arr, k);
return 0;
}
Java
import java.util.*;
class GfG {
// Function to calculate Kth largest element
// in contiguous subarray sum
static int kthLargest(int[] arr, int k) {
int n = arr.length;
// array to store prefix sums
int[] sum = new int[n + 1];
sum[0] = 0;
sum[1] = arr[0];
for (int i = 2; i <= n; i++)
sum[i] = sum[i - 1] + arr[i - 1];
// min heap
PriorityQueue<Integer> pq = new PriorityQueue<>();
// loop to calculate the contiguous subarray
// sums position-wise
for (int i = 1; i <= n; i++) {
// loop to traverse all positions that
// form contiguous subarray
for (int j = i; j <= n; j++) {
// calculates the contiguous subarray
// sums from j to i index
int x = sum[j] - sum[i - 1];
// if queue has less than k elements,
// then simply push it
if (pq.size() < k)
pq.add(x);
else {
// it the min heap has equal to
// k elements then just check
// if the largest kth element is
// smaller than x then insert
// else its of no use
if (pq.peek() < x) {
pq.poll();
pq.add(x);
}
}
}
}
// the top element will be then kth
// largest element
return pq.peek();
}
public static void main(String[] args) {
int[] arr = {20, -5, -1};
int k = 3;
System.out.println(kthLargest(arr, k));
}
}
Python
import heapq
# Function to calculate Kth largest element
# in contiguous subarray sum
def kthLargest(arr, k):
n = len(arr)
# array to store prefix sums
sum = [0] * (n + 1)
sum[0] = 0
sum[1] = arr[0]
for i in range(2, n + 1):
sum[i] = sum[i - 1] + arr[i - 1]
# min heap
pq = []
# loop to calculate the contiguous subarray
# sums position-wise
for i in range(1, n + 1):
# loop to traverse all positions that
# form contiguous subarray
for j in range(i, n + 1):
# calculates the contiguous subarray
# sums from j to i index
x = sum[j] - sum[i - 1]
# if queue has less than k elements,
# then simply push it
if len(pq) < k:
heapq.heappush(pq, x)
else:
# it the min heap has equal to
# k elements then just check
# if the largest kth element is
# smaller than x then insert
# else its of no use
if pq[0] < x:
heapq.heapreplace(pq, x)
# the top element will be then kth
# largest element
return pq[0]
# Driver's code
if __name__ == "__main__":
arr = [20, -5, -1]
k = 3
# Function call
print(kthLargest(arr, k))
C#
// C# program to find the K-th
// largest sum of subarray
using System;
using System.Collections.Generic;
class GfG{
// function to calculate Kth largest
// element in contiguous subarray sum
static int kthLargest(int[] arr, int N, int K){
// array to store prefix sums
int[] sum = new int[N + 1];
sum[0] = 0;
sum[1] = arr[0];
for (int i = 2; i <= N; i++)
sum[i] = sum[i - 1] + arr[i - 1];
// priority_queue of min heap
List<int> Q = new List<int>();
// loop to calculate the contiguous subarray
// sum position-wise
for (int i = 1; i <= N; i++) {
// loop to traverse all positions that
// form contiguous subarray
for (int j = i; j <= N; j++) {
// calculates the contiguous subarray
// sum from j to i index
int x = sum[j] - sum[i - 1];
// if queue has less than k elements,
// then simply push it
if (Q.Count < K)
Q.Add(x);
else {
// it the min heap has equal to
// k elements then just check
// if the largest kth element is
// smaller than x then insert
// else its of no use
Q.Sort();
if (Q[0] < x) {
Q.RemoveAt(0);
Q.Add(x);
}
}
Q.Sort();
}
}
// the top element will be then Kth
// largest element
return Q[0];
}
// Driver's Code
public static void Main(String[] args)
{
int[] a = new int[] { 20, -5, -1 };
int N = a.Length;
int K = 3;
// Function call
Console.WriteLine(kthLargest(a, N, K));
}
}
// This code contributed by Rajput-Ji
JavaScript
// Custom MinHeap class to act as a priority queue
class MinHeap {
constructor() {
this.heap = [];
}
// Return the top (minimum) element
peek() {
return this.heap[0];
}
// Insert a new value into the heap
insert(val) {
this.heap.push(val);
this._heapifyUp(this.heap.length - 1);
}
// Remove and return the top (minimum) element
extractMin() {
if (this.heap.length === 0) return null;
if (this.heap.length === 1) return this.heap.pop();
const min = this.heap[0];
this.heap[0] = this.heap.pop();
this._heapifyDown(0);
return min;
}
size() {
return this.heap.length;
}
// Helper to maintain heap property after insertion
_heapifyUp(index) {
while (index > 0) {
const parent = Math.floor((index - 1) / 2);
if (this.heap[parent] > this.heap[index]) {
[this.heap[parent], this.heap[index]] = [this.heap[index], this.heap[parent]];
index = parent;
} else {
break;
}
}
}
// Helper to maintain heap property after removal
_heapifyDown(index) {
const n = this.heap.length;
while (true) {
let smallest = index;
const left = 2 * index + 1;
const right = 2 * index + 2;
if (left < n && this.heap[left] < this.heap[smallest]) {
smallest = left;
}
if (right < n && this.heap[right] < this.heap[smallest]) {
smallest = right;
}
if (smallest !== index) {
[this.heap[index], this.heap[smallest]] = [this.heap[smallest], this.heap[index]];
index = smallest;
} else {
break;
}
}
}
}
// Function to find the Kth largest subarray sum
function kthLargest(arr, k) {
const n = arr.length;
// Create prefix sum array
const prefix = new Array(n + 1).fill(0);
for (let i = 1; i <= n; i++) {
prefix[i] = prefix[i - 1] + arr[i - 1];
}
// Use MinHeap to keep track of top K largest sums
const pq = new MinHeap();
for (let i = 1; i <= n; i++) {
for (let j = i; j <= n; j++) {
const sum = prefix[j] - prefix[i - 1];
if (pq.size() < k) {
pq.insert(sum);
} else if (pq.peek() < sum) {
pq.extractMin();
pq.insert(sum);
}
}
}
return pq.peek();
}
// Driver Code
let arr = [20, -5, -1];
let k = 3;
console.log(kthLargest(arr, k)); // Output: 14
Similar Reads
Basics & Prerequisites
Data Structures
Array Data StructureIn this article, we introduce array, implementation in different popular languages, its basic operations and commonly seen problems / interview questions. An array stores items (in case of C/C++ and Java Primitive Arrays) or their references (in case of Python, JS, Java Non-Primitive) at contiguous
3 min read
String in Data StructureA string is a sequence of characters. The following facts make string an interesting data structure.Small set of elements. Unlike normal array, strings typically have smaller set of items. For example, lowercase English alphabet has only 26 characters. ASCII has only 256 characters.Strings are immut
2 min read
Hashing in Data StructureHashing is a technique used in data structures that efficiently stores and retrieves data in a way that allows for quick access. Hashing involves mapping data to a specific index in a hash table (an array of items) using a hash function. It enables fast retrieval of information based on its key. The
2 min read
Linked List Data StructureA linked list is a fundamental data structure in computer science. It mainly allows efficient insertion and deletion operations compared to arrays. Like arrays, it is also used to implement other data structures like stack, queue and deque. Hereâs the comparison of Linked List vs Arrays Linked List:
2 min read
Stack Data StructureA Stack is a linear data structure that follows a particular order in which the operations are performed. The order may be LIFO(Last In First Out) or FILO(First In Last Out). LIFO implies that the element that is inserted last, comes out first and FILO implies that the element that is inserted first
2 min read
Queue Data StructureA Queue Data Structure is a fundamental concept in computer science used for storing and managing data in a specific order. It follows the principle of "First in, First out" (FIFO), where the first element added to the queue is the first one to be removed. It is used as a buffer in computer systems
2 min read
Tree Data StructureTree Data Structure is a non-linear data structure in which a collection of elements known as nodes are connected to each other via edges such that there exists exactly one path between any two nodes. Types of TreeBinary Tree : Every node has at most two childrenTernary Tree : Every node has at most
4 min read
Graph Data StructureGraph Data Structure is a collection of nodes connected by edges. It's used to represent relationships between different entities. If you are looking for topic-wise list of problems on different topics like DFS, BFS, Topological Sort, Shortest Path, etc., please refer to Graph Algorithms. Basics of
3 min read
Trie Data StructureThe Trie data structure is a tree-like structure used for storing a dynamic set of strings. It allows for efficient retrieval and storage of keys, making it highly effective in handling large datasets. Trie supports operations such as insertion, search, deletion of keys, and prefix searches. In this
15+ min read
Algorithms
Searching AlgorithmsSearching algorithms are essential tools in computer science used to locate specific items within a collection of data. In this tutorial, we are mainly going to focus upon searching in an array. When we search an item in an array, there are two most common algorithms used based on the type of input
2 min read
Sorting AlgorithmsA Sorting Algorithm is used to rearrange a given array or list of elements in an order. For example, a given array [10, 20, 5, 2] becomes [2, 5, 10, 20] after sorting in increasing order and becomes [20, 10, 5, 2] after sorting in decreasing order. There exist different sorting algorithms for differ
3 min read
Introduction to RecursionThe process in which a function calls itself directly or indirectly is called recursion and the corresponding function is called a recursive function. A recursive algorithm takes one step toward solution and then recursively call itself to further move. The algorithm stops once we reach the solution
14 min read
Greedy AlgorithmsGreedy algorithms are a class of algorithms that make locally optimal choices at each step with the hope of finding a global optimum solution. At every step of the algorithm, we make a choice that looks the best at the moment. To make the choice, we sometimes sort the array so that we can always get
3 min read
Graph AlgorithmsGraph is a non-linear data structure like tree data structure. The limitation of tree is, it can only represent hierarchical data. For situations where nodes or vertices are randomly connected with each other other, we use Graph. Example situations where we use graph data structure are, a social net
3 min read
Dynamic Programming or DPDynamic Programming is an algorithmic technique with the following properties.It is mainly an optimization over plain recursion. Wherever we see a recursive solution that has repeated calls for the same inputs, we can optimize it using Dynamic Programming. The idea is to simply store the results of
3 min read
Bitwise AlgorithmsBitwise algorithms in Data Structures and Algorithms (DSA) involve manipulating individual bits of binary representations of numbers to perform operations efficiently. These algorithms utilize bitwise operators like AND, OR, XOR, NOT, Left Shift, and Right Shift.BasicsIntroduction to Bitwise Algorit
4 min read
Advanced
Segment TreeSegment Tree is a data structure that allows efficient querying and updating of intervals or segments of an array. It is particularly useful for problems involving range queries, such as finding the sum, minimum, maximum, or any other operation over a specific range of elements in an array. The tree
3 min read
Pattern SearchingPattern searching algorithms are essential tools in computer science and data processing. These algorithms are designed to efficiently find a particular pattern within a larger set of data. Patten SearchingImportant Pattern Searching Algorithms:Naive String Matching : A Simple Algorithm that works i
2 min read
GeometryGeometry is a branch of mathematics that studies the properties, measurements, and relationships of points, lines, angles, surfaces, and solids. From basic lines and angles to complex structures, it helps us understand the world around us.Geometry for Students and BeginnersThis section covers key br
2 min read
Interview Preparation
Practice Problem