Given an array of ‘N’ integers and ‘Q’ queries. The query is defined as below :-
Given 2 integers ‘l’ and ‘r’ (‘l’ >= 0 and ‘r’ < N) find the maximum subarray sum between ‘l’ to ‘r’ (Inclusive).
Query( ‘l’ ,’r’) = max(arr[i] + arr[i+1] +...arr[j].( i >= ‘l’ and j <= ‘r’)
Input Format :
The first line contains ‘T,’ denoting the number of test cases.
The first line of the test case contains a single integer ‘N’ denoting the size of the ‘arr’ array.
The second line of each test case contains ‘N’ space-separated integers denoting the array ‘arr’.
The third line of each test case contains an integer ‘Q’ denoting the number of queries.
The next ‘Q' lines of each test case contain 2 space-separated integers denoting the following:
The first integer denotes ‘l’ and the second integer denotes ‘r’ which are the range for which we need to calculate max(arr[i] + arr[i+1] +...arr[j].( i >= ‘l’ and j <= ‘r’).
Output Format :
For each query print an integer denoting the maximum possible value.in the range of ‘l’ and ‘r’.
The output for each test case will be printed in a separate line.
Note :
You need not to print anything. It has been already taken care of. Just implement the function.
Constraints :
1 <= T <= 5
1 <= N <= 10^5
1 <= Q <= 10^5
-10^9 <= arr[i] <= 10^9
Where ‘arr[i]’ is the value of the element at index ‘i’.
Time Limit: 1 sec
The key idea is to process the queries as asked. Forgiven ‘l’ and ‘r’ we need to find the maximum sub-array sum from ‘l’ to ‘r’. For this, we can use the Kadane algorithm. To know more about the Kadane algorithm refer to this:-
https://cp-algorithms.com/others/maximum_average_segment.html
Space Complexity: O(1)Explanation:O(1)
We are using constant space to solve this.
Time Complexity: O(n^2)Explanation:O(N * Q) where ‘N’ is the size of array and ‘Q’ are the number of queries.
In the worse case, we need to find subarray sum from 0 to N - 1 Q times. The time complexity of Kadane is O(N) hence the worse case complexity will be O(N * Q).
Python (3.5)
"""
Time Complexity : O(N * Q)
Space Complexity : O(1)
where N is size of array and Q is number of queries.
"""
def kadane(arr, l, r):
ans = -999999999
summ = 0
for i in range(l, r+1):
summ += arr[i]
ans = max(ans, summ)
if (summ < 0):
summ = 0
return ans
def solve(n, arr, q, queries):
ans1 = []
for i in range(q):
# Kadane will find max_subarray summ witihin given range.
ans = kadane(arr, queries[i][0], queries[i][1])
ans1.append(ans)
return ans1
C++ (g++ 5.4)
/*
Time Complexity : O(N * Q)
Space Complexity : O(1)
where N is size of array and Q is number of queries.
*/
#include
int kadane(vector &arr, int l, int r)
{
int ans = INT_MIN;
int sum = 0;
for (int i = l; i <= r; i++)
{
sum += arr[i];
ans = max(ans, sum);
if (sum < 0)
{
sum = 0;
}
}
return ans;
}
vector solve(int n, vector &arr, int q, vector> &queries)
{
vectorans1;
for (int i = 0; i < q; i++)
{
// Kadane will find max_subarray sum witihin given range.
int ans = kadane(arr, queries[i][0], queries[i][1]);
ans1.push_back(ans);
}
return ans1;
}
Java (SE 1.8)
/*
Time Complexity : O(N * Q)
Space Complexity : O(1)
where N is size of array and Q is number of queries.
*/
public class Solution
{
public static int kadane(int[] arr, int l, int r)
{
int ans = Integer.MIN_VALUE;
int sum = 0;
for (int i = l; i <= r; i++)
{
sum += arr[i];
ans = Math.max(ans, sum);
if (sum < 0)
{
sum = 0;
}
}
return ans;
}
public static int[] solve(int n, int[] arr, int q, int[][] queries)
{
int[] ans1 = new int[q];
for (int i = 0; i < q; i++)
{
// Kadane will find max_subarray sum witihin given range.
int ans = kadane(arr, queries[i][0], queries[i][1]);
ans1[i] = ans;
}
return ans1;
}
}
The main idea is to process the queries efficiently we will use a segment tree.To know more about segment tree refer this :- https://cp-algorithms.com/data_structures/segment_tree.html
At each node in the segment tree we will store 4 values:-
Sum:- The sum of all numbers in the subsegment which a particular node denotes to.
Max_Sum:- We will store the maximum possible sub-array sum of a particular segment.
Max_Prefix_Sum:- This denotes the maximum prefix sum of the segment.
Max_Suffix_Sum:- This denotes the maximum suffix sum of the segment.
Using these four values we can get the answer query for any segment.
Now to combine the answer from two child nodes we have to do the following:-
The Sum for the parent node will be:-
parent.Sum = leftChild.sum + rightChild.sum
parent.Max_Sum = max( leftChild.Max_Sum , rightChild.Max_Sum , leftChild.MaxSuffix_Sum + rightChild.MaxPreffix_Sum)
The reason for this is:-
The Max_sum for a parent can be is maximum of leftChild.Max_Sum and rightChild.Max_Sum and sum of Suffix_Sum of left and Preffix_Sum of right.
Max_Suffix of a parent is maximum of right child Suffix_Sum and left Child SuffixSum plus sum of rightChild.
Max_Prefix of the parent is maximum of left child Preffix_Sum and right Child PreffixSum plus the sum of left child.
Space Complexity: O(n)Explanation:O(N) where N is the size of given array.
We are creating an array of size 4* N + 1 . Thus space complexity will be O(N).
Time Complexity: O(nlogn)Explanation:O(N * log(N) + Q*log(N) ) where ‘N’ is the size of the array and ‘Q' are the number of queries.
We have to build segment tree which takes N*log(N) and we have to process Q queries and each query takes log(N) time with the segment tree .
Python (3.5)
"""
Time Complexity: O(N*log(N) + Q*log(N))
Space Complexity: O(N)
where N is size of array and Q is number of queries.
"""
class obj:
def __init__(self):
summ = 0
max_sum = 0
max_suffix_sum = 0
max_prefix_sum = 0
class segmentTree:
def __init__(self, n):
self.segment = []
for i in range(4*n + 2):
self.segment.append(obj())
def buildTree(self, arr, l, r, index=0):
if(l > r):
return
# It means it has only 1 element
if(l == r):
self.segment[index].max_sum = arr[l]
self.segment[index].max_prefix_sum = arr[l]
self.segment[index].max_suffix_sum = arr[l]
self.segment[index].summ = arr[l]
return
mid = (l + r) // 2
lChild = 2 * index + 1
rChild = 2 * index + 2
self.buildTree(arr, l, mid, lChild)
self.buildTree(arr, mid + 1, r, rChild)
# Merging ans from leftChild and rightChild.
self.segment[index].summ = self.segment[lChild].summ + \
self.segment[rChild].summ
self.segment[index].max_prefix_sum = max(
self.segment[lChild].max_prefix_sum, self.segment[lChild].summ + self.segment[rChild].max_prefix_sum)
self.segment[index].max_suffix_sum = max(
self.segment[rChild].max_suffix_sum, self.segment[rChild].summ + self.segment[lChild].max_suffix_sum)
self.segment[index].max_sum = max(self.segment[lChild].max_sum, max(
self.segment[rChild].max_sum, self.segment[lChild].max_suffix_sum + self.segment[rChild].max_prefix_sum))
def query(self, l, r, ql, qr, index=0):
# If the l and r lies inside queries range then that complete node is part of ans.
if (ql <= l and qr >= r):
return self.segment[index]
mid = (l + r) // 2
# If the leftChild has no overlapping with queries range then ans only lies in right part.
if (mid < ql):
return self.query(mid + 1, r, ql, qr, 2 * index + 2)
# If the rightChild has no overlapping with queries range then ans only lies in left part.
if (mid + 1 > qr):
return self.query(l, mid, ql, qr, 2 * index + 1)
ans1 = self.query(l, mid, ql, qr, 2 * index + 1)
ans2 = self.query(mid + 1, r, ql, qr, 2 * index + 2)
ans = obj()
# Merging answer from left and right child.
ans.summ = ans1.summ + ans2.summ
ans.max_sum = max(ans1.max_sum, max(
ans2.max_sum, ans1.max_suffix_sum + ans2.max_prefix_sum))
ans.max_prefix_sum = max(
ans1.max_prefix_sum, ans1.summ + ans2.max_prefix_sum)
ans.max_suffix_sum = max(
ans2.max_suffix_sum, ans2.summ + ans1.max_suffix_sum)
return ans
def solve(n, arr, q, queries):
tree = segmentTree(n)
# Building tree corresponding to array.
tree.buildTree(arr, 0, n - 1)
ans1 = []
for i in range(q):
ans = tree.query(0, n - 1, queries[i][0], queries[i][1])
ans1.append(ans.max_sum)
return ans1
C++ (g++ 5.4)
/*
Time Complexity : O(N*log(N) + Q*log(N))
Space Complexity : O(N)
where N is size of array and Q is number of queries.
*/
class obj {
public:
int sum;
int max_sum;
int max_prefix_sum;
int max_suffix_sum;
obj()
{
sum = 0;
max_sum = 0;
max_suffix_sum = 0;
max_prefix_sum = 0;
}
};
class segmentTree {
public:
vectorsegment;
segmentTree(int n)
{
// Creating a segment tree of size 4*N + 1.
segment = vector(4 * n + 1);
}
void buildTree(vector& arr, int l, int r, int index = 0)
{
if (l > r)
{
return ;
}
// It means it has only one element
if (l == r)
{
segment[index].max_sum = arr[l];
segment[index].max_prefix_sum = arr[l];
segment[index].max_suffix_sum = arr[l];
segment[index].sum = arr[l];
return ;
}
int mid = (l + r) / 2;
int lChild = 2 * index + 1;
int rChild = 2 * index + 2;
buildTree(arr, l, mid, lChild);
buildTree(arr, mid + 1, r, rChild);
// Merging ans from leftChild and rightChild.
segment[index].sum = segment[lChild].sum + segment[rChild].sum;
segment[index].max_prefix_sum = max(segment[lChild].max_prefix_sum, segment[lChild].sum + segment[rChild].max_prefix_sum);
segment[index].max_suffix_sum = max(segment[rChild].max_suffix_sum, segment[rChild].sum + segment[lChild].max_suffix_sum);
segment[index].max_sum = max(segment[lChild].max_sum, max(segment[rChild].max_sum, segment[lChild].max_suffix_sum + segment[rChild].max_prefix_sum));
}
obj query(int l, int r, int ql, int qr, int index)
{
// If the l and r lies inside queries range then that complete node is part of ans.
if (ql <= l && qr >= r)
{
return segment[index];
}
int mid = (l + r) / 2;
// If the leftChild has no overlapping with queries range then ans only lies in right part.
if (mid < ql)
{
return query(mid + 1, r, ql, qr, 2 * index + 2);
}
// If the rightChild has no overlapping with queries range then ans only lies in left part.
if (mid + 1 > qr)
{
return query(l, mid, ql, qr, 2 * index + 1);
}
obj ans1 = query(l, mid, ql, qr, 2 * index + 1);
obj ans2 = query(mid + 1, r, ql, qr, 2 * index + 2);
obj ans;
// Merging answer from left and right child.
ans.sum = ans1.sum + ans2.sum;
ans.max_sum = max(ans1.max_sum, max(ans2.max_sum, ans1.max_suffix_sum + ans2.max_prefix_sum));
ans.max_prefix_sum = max(ans1.max_prefix_sum, ans1.sum + ans2.max_prefix_sum);
ans.max_suffix_sum = max(ans2.max_suffix_sum, ans2.sum + ans1.max_suffix_sum);
return ans;
}
int query(int l, int r, int ql, int qr)
{
obj ans = query(l, r, ql, qr, 0);
return ans.max_sum;
}
};
vector solve(int n, vector &arr, int q, vector> &queries)
{
segmentTree tree(n);
// Building tree corresponding to array.
tree.buildTree(arr, 0, n - 1);
vectorans1;
for (int i = 0; i < q; i++)
{
int ans = tree.query(0, n - 1, queries[i][0], queries[i][1]);
ans1.push_back(ans);
}
return ans1;
}
Java (SE 1.8)
/*
Time Complexity: O(N*log(N) + Q*log(N))
Space Complexity: O(N)
where N is size of array and Q is number of queries.
*/
class obj
{
public int sum;
public int max_sum;
public int max_prefix_sum;
public int max_suffix_sum;
obj()
{
sum = 0;
max_sum = 0;
max_suffix_sum = 0;
max_prefix_sum = 0;
}
};
class segmentTree
{
public obj[] segment;
segmentTree(int n)
{
segment = new obj[4*n + 1];
// Creating a segment tree of size 4*N+1.
for(int i=0 ; i<4*n ; i++)
{
segment[i] = new obj();
}
}
void buildTree(int[] arr, int l, int r, int index)
{
if (l > r)
{
return ;
}
// It means it has only one element
if (l == r)
{
segment[index].max_sum = arr[l];
segment[index].max_prefix_sum = arr[l];
segment[index].max_suffix_sum = arr[l];
segment[index].sum = arr[l];
return ;
}
int mid = (l + r) / 2;
int lChild = 2 * index + 1;
int rChild = 2 * index + 2;
buildTree(arr, l, mid, lChild);
buildTree(arr, mid + 1, r, rChild);
// Merging ans from leftChild and rightChild.
segment[index].sum = segment[lChild].sum + segment[rChild].sum;
segment[index].max_prefix_sum = Math.max(segment[lChild].max_prefix_sum, segment[lChild].sum + segment[rChild].max_prefix_sum);
segment[index].max_suffix_sum = Math.max(segment[rChild].max_suffix_sum, segment[rChild].sum + segment[lChild].max_suffix_sum);
segment[index].max_sum = Math.max(segment[lChild].max_sum, Math.max(segment[rChild].max_sum, segment[lChild].max_suffix_sum + segment[rChild].max_prefix_sum));
}
obj query(int l, int r, int ql, int qr, int index)
{
// If the l and r lies inside queries range then that complete node is part of ans.
if (ql <= l && qr >= r)
{
return segment[index];
}
int mid = (l + r) / 2;
// If the leftChild has no overlapping with queries range then ans only lies in right part.
if (mid < ql)
{
return query(mid + 1, r, ql, qr, 2 * index + 2);
}
// If the rightChild has no overlapping with queries range then ans only lies in left part.
if (mid + 1 > qr)
{
return query(l, mid, ql, qr, 2 * index + 1);
}
obj ans1 = query(l, mid, ql, qr, 2 * index + 1);
obj ans2 = query(mid + 1, r, ql, qr, 2 * index + 2);
obj ans = new obj();
// Merging answer from left and right child.
ans.sum = ans1.sum + ans2.sum;
ans.max_sum = Math.max(ans1.max_sum, Math.max(ans2.max_sum, ans1.max_suffix_sum + ans2.max_prefix_sum));
ans.max_prefix_sum = Math.max(ans1.max_prefix_sum, ans1.sum + ans2.max_prefix_sum);
ans.max_suffix_sum = Math.max(ans2.max_suffix_sum, ans2.sum + ans1.max_suffix_sum);
return ans;
}
int query(int l, int r, int ql, int qr)
{
obj ans = query(l, r, ql, qr, 0);
return ans.max_sum;
}
};
public class Solution
{
public static int[] solve(int n, int[] arr, int q, int[][] queries)
{
segmentTree tree = new segmentTree(n);
// Building tree corresponding to array.
tree.buildTree(arr, 0, n - 1, 0);
int[] ans1 = new int[q];
for (int i = 0; i < q; i++)
{
int ans = tree.query(0, n - 1, queries[i][0], queries[i][1]);
ans1[i] = ans;
}
return ans1;
}
}
Top Freshworks Software Developer interview questions & answers
Popular interview questions of Software Developer
Reviews
Interviews
Salaries
Users/Month