Open In App

Maximum of all subarrays of size K using Segment Tree

Improve
Improve
Like Article
Like
Save
Share
Report

Given an array arr[] and an integer K, the task is to find the maximum for each and every contiguous subarray of size K.

Examples: 

Input: arr[] = {1, 2, 3, 1, 4, 5, 2, 3, 6}, K = 3 
Output: 3 3 4 5 5 5 6 
Explanation
Maximum of 1, 2, 3 is 3 
Maximum of 2, 3, 1 is 3 
Maximum of 3, 1, 4 is 4 
Maximum of 1, 4, 5 is 5 
Maximum of 4, 5, 2 is 5 
Maximum of 5, 2, 3 is 5 
Maximum of 2, 3, 6 is 6

Input: arr[] = {8, 5, 10, 7, 9, 4, 15, 12, 90, 13}, K = 4 
Output: 10 10 10 15 15 90 90 
Explanation: 
Maximum of first 4 elements is 10, similarly for next 4 
elements (i.e from index 1 to 4) is 10, So the sequence 
generated is 10 10 10 15 15 90 90 

Approach
The idea is to use the Segment tree to answer the maximum of all subarrays of size K.

  1. Representation of Segment trees 
    • Leaf Nodes are the elements of the input array.
    • Each internal node represents the maximum of all of its children.
  2. Construction of Segment Tree from the given array: 
    • We start with a segment arr[0 . . . n-1], and every time we divide the current segment into two halves(if it has not yet become a segment of length 1), and then call the same procedure on both halves, and for each such segment, we store the maximum value in a segment tree node.
    • All levels of the constructed segment tree will be completely filled except the last level. Also, the tree will be a full Binary Tree because we always divide segments into two halves at every level.
    • Since the constructed tree is always a full binary tree with n leaves, there will be n – 1 internal nodes. So total nodes will be 2 * n – 1.
    • The height of the segment tree will be log2n.
    • Since the tree is represented using an array and the relation between parent and child indexes must be maintained, the size of memory allocated for the segment tree will be 2 *(2ceil(log2n))-1.

Below is the implementation of the above approach. 

C++




// C++  program to answer Maximum
// of allsubarrays of size k
// using segment tree
#include <bits/stdc++.h>
using namespace std;
 
#define MAX 1000000
 
// Size of segment
// tree = 2^{log(MAX)+1}
int st[3 * MAX];
 
// A utility function to get the
// middle index of given range.
int getMid(int s, int e)
{
    return s + (e - s) / 2;
}
// A recursive function that
// constructs Segment Tree for
// array[s...e]. node is index
// of current node in segment
// tree st
void constructST(int node, int s,
                 int e, int arr[])
{
    // If there is one element in
    // array, store it in current
    // node of segment tree and return
    if (s == e) {
        st[node] = arr[s];
        return;
    }
    // If there are more than
    // one elements, then recur
    // for left and right subtrees
    // and store the max of
    // values in this node
    int mid = getMid(s, e);
 
    constructST(2 * node, s,
                mid, arr);
    constructST(2 * node + 1,
                mid + 1, e,
                arr);
    st[node] = max(st[2 * node],
                   st[2 * node + 1]);
}
 
/* A recursive function to get the
   maximum of range[l, r] The
   following parameters for
   this function:
 
st     -> Pointer to segment tree
node   -> Index of current node in
          the segment tree .
s & e  -> Starting and ending indexes
          of the segment represented
          by current node, i.e., st[node]
l & r  -> Starting and ending indexes
          of range query
 */
int getMax(int node, int s,
           int e, int l,
           int r)
{
    // If segment of this node
    // does not belong to
    // given range
    if (s > r || e < l)
        return INT_MIN;
 
    // If segment of this node
    // is completely part of
    // given range, then return
    // the max of segment
    if (s >= l && e <= r)
        return st[node];
 
    // If segment of this node
    // is partially the part
    // of given range
    int mid = getMid(s, e);
 
    return max(getMax(2 * node,
                      s, mid,
                      l, r),
               getMax(2 * node + 1,
                      mid + 1, e,
                      l, r));
}
 
// Function to print the max
// of all subarrays of size k
void printKMax(int n, int k)
{
    for (int i = 0; i < n; i++) {
        if ((k - 1 + i) < n)
            cout << getMax(1, 0, n - 1,
                           i, k - 1 + i)
                 << " ";
        else
            break;
    }
}
 
// Driver code
int main()
{
    int k = 4;
    int arr[] = { 8, 5, 10, 7, 9, 4, 15,
                  12, 90, 13 };
    int n = sizeof(arr) / sizeof(arr[0]);
 
    // Function to construct the
    // segment tree
    constructST(1, 0, n - 1, arr);
 
    printKMax(n, k);
 
    return 0;
}


Java




// Java program to answer Maximum
// of allsubarrays of size k
// using segment tree
import java.io.*;
import java.util.*;
 
class GFG{
 
static int MAX = 1000000;
 
// Size of segment
// tree = 2^{log(MAX)+1}
static int[] st = new int[3 * MAX];
 
// A utility function to get the
// middle index of given range.
static int getMid(int s, int e)
{
    return s + (e - s) / 2;
}
 
// A recursive function that
// constructs Segment Tree for
// array[s...e]. node is index
// of current node in segment
// tree st
static void constructST(int node, int s,
                        int e, int[] arr)
{
     
    // If there is one element in
    // array, store it in current
    // node of segment tree and return
    if (s == e)
    {
        st[node] = arr[s];
        return;
    }
     
    // If there are more than
    // one elements, then recur
    // for left and right subtrees
    // and store the max of
    // values in this node
    int mid = getMid(s, e);
 
    constructST(2 * node, s, mid, arr);
    constructST(2 * node + 1,
                mid + 1, e, arr);
     
    st[node] = Math.max(st[2 * node],
                        st[2 * node + 1]);
}
 
/* A recursive function to get the
   maximum of range[l, r] The
   following parameters for
   this function:
 
st     -> Pointer to segment tree
node   -> Index of current node in
          the segment tree .
s & e  -> Starting and ending indexes
          of the segment represented
          by current node, i.e., st[node]
l & r  -> Starting and ending indexes
          of range query
 */
static int getMax(int node, int s, int e,
                            int l, int r)
{
     
    // If segment of this node
    // does not belong to
    // given range
    if (s > r || e < l)
        return Integer.MIN_VALUE;
 
    // If segment of this node
    // is completely part of
    // given range, then return
    // the max of segment
    if (s >= l && e <= r)
        return st[node];
 
    // If segment of this node
    // is partially the part
    // of given range
    int mid = getMid(s, e);
 
    return Math.max(getMax(2 * node, s,
                           mid, l, r),
                    getMax(2 * node + 1,
                           mid + 1, e, l, r));
}
 
// Function to print the max
// of all subarrays of size k
static void printKMax(int n, int k)
{
    for(int i = 0; i < n; i++)
    {
        if ((k - 1 + i) < n)
            System.out.print(getMax(1, 0, n - 1,
                                    i, k - 1 + i) + " ");
        else
            break;
    }
}
 
// Driver code
public static void main(String[] args)
{
    int k = 4;
    int[] arr = { 8, 5, 10, 7, 9,
                  4, 15, 12, 90, 13 };
    int n = arr.length;
 
    // Function to construct the
    // segment tree
    constructST(1, 0, n - 1, arr);
 
    printKMax(n, k);
}
}
 
// This code is contributed by akhilsaini


Python3




# Python3 program to answer maximum
# of all subarrays of size k
# using segment tree
import sys
 
MAX = 1000000
 
# Size of segment
# tree = 2^{log(MAX)+1}
st = [0] * (3 * MAX)
 
# A utility function to get the
# middle index of given range.
def getMid(s, e):
    return s + (e - s) // 2
     
# A recursive function that
# constructs Segment Tree for
# array[s...e]. node is index
# of current node in segment
# tree st
def constructST(node, s, e, arr):
 
    # If there is one element in
    # array, store it in current
    # node of segment tree and return
    if (s == e):
        st[node] = arr[s]
        return
 
    # If there are more than
    # one elements, then recur
    # for left and right subtrees
    # and store the max of
    # values in this node
    mid = getMid(s, e)
    constructST(2 * node, s, mid, arr)
    constructST(2 * node + 1, mid + 1, e, arr)
    st[node] = max(st[2 * node], st[2 * node + 1])
 
''' A recursive function to get the
maximum of range[l, r] The
following parameters for
this function:
 
st     -> Pointer to segment tree
node -> Index of current node in
        the segment tree .
s & e -> Starting and ending indexes
        of the segment represented
        by current node, i.e., st[node]
l & r -> Starting and ending indexes
        of range query
'''
def getMax(node, s, e, l, r):
 
    # If segment of this node
    # does not belong to
    # given range
    if (s > r or e < l):
        return (-sys.maxsize - 1)
 
    # If segment of this node
    # is completely part of
    # given range, then return
    # the max of segment
    if (s >= l and e <= r):
        return st[node]
 
    # If segment of this node
    # is partially the part
    # of given range
    mid = getMid(s, e)
 
    return max(getMax(2 * node, s, mid, l, r),
               getMax(2 * node + 1, mid + 1, e, l, r))
 
# Function to print the max
# of all subarrays of size k
def printKMax(n, k):
 
    for i in range(n):
        if ((k - 1 + i) < n):
            print(getMax(1, 0, n - 1, i,
                               k - 1 + i), end = " ")
        else:
            break
 
# Driver code
if __name__ == "__main__":
     
    k = 4
    arr = [ 8, 5, 10, 7, 9, 4, 15, 12, 90, 13 ]
    n = len(arr)
 
    # Function to construct the
    # segment tree
    constructST(1, 0, n - 1, arr)
     
    printKMax(n, k)
 
# This code is contributed by chitranayal


C#




// C# program to answer Maximum
// of allsubarrays of size k
// using segment tree
using System;
 
class GFG{
 
static int MAX = 1000000;
 
// Size of segment
// tree = 2^{log(MAX)+1}
static int[] st = new int[3 * MAX];
 
// A utility function to get the
// middle index of given range.
static int getMid(int s, int e)
{
    return s + (e - s) / 2;
}
 
// A recursive function that
// constructs Segment Tree for
// array[s...e]. node is index
// of current node in segment
// tree st
static void constructST(int node, int s,
                        int e, int[] arr)
{
     
    // If there is one element in
    // array, store it in current
    // node of segment tree and return
    if (s == e)
    {
        st[node] = arr[s];
        return;
    }
     
    // If there are more than
    // one elements, then recur
    // for left and right subtrees
    // and store the max of
    // values in this node
    int mid = getMid(s, e);
 
    constructST(2 * node, s, mid, arr);
    constructST(2 * node + 1, mid + 1, e, arr);
     
    st[node] = Math.Max(st[2 * node],
                        st[2 * node + 1]);
}
 
/* A recursive function to get the
   maximum of range[l, r] The
   following parameters for
   this function:
 
st     -> Pointer to segment tree
node   -> Index of current node in
          the segment tree .
s & e  -> Starting and ending indexes
          of the segment represented
          by current node, i.e., st[node]
l & r  -> Starting and ending indexes
          of range query
 */
static int getMax(int node, int s, int e,
                            int l, int r)
{
     
    // If segment of this node
    // does not belong to
    // given range
    if (s > r || e < l)
        return int.MinValue;
 
    // If segment of this node
    // is completely part of
    // given range, then return
    // the max of segment
    if (s >= l && e <= r)
        return st[node];
 
    // If segment of this node
    // is partially the part
    // of given range
    int mid = getMid(s, e);
 
    return Math.Max(getMax(2 * node, s,
                           mid, l, r),
                    getMax(2 * node + 1,
                           mid + 1, e, l, r));
}
 
// Function to print the max
// of all subarrays of size k
static void printKMax(int n, int k)
{
    for(int i = 0; i < n; i++)
    {
        if ((k - 1 + i) < n)
            Console.Write(getMax(1, 0, n - 1,
                                 i, k - 1 + i) + " ");
        else
            break;
    }
}
 
// Driver code
public static void Main()
{
    int k = 4;
    int[] arr = { 8, 5, 10, 7, 9,
                  4, 15, 12, 90, 13 };
    int n = arr.Length;
 
    // Function to construct the
    // segment tree
    constructST(1, 0, n - 1, arr);
 
    printKMax(n, k);
}
}
 
// This code is contributed by akhilsaini


Javascript




<script>
 
// Javascript program to answer Maximum
// of allsubarrays of size k
// using segment tree
 
var MAX = 1000000;
 
// Size of segment
// tree = 2^{log(MAX)+1}
var st = Array(3*MAX);
 
// A utility function to get the
// middle index of given range.
function getMid(s, e)
{
    return s + parseInt((e - s) / 2);
}
// A recursive function that
// constructs Segment Tree for
// array[s...e]. node is index
// of current node in segment
// tree st
function constructST(node, s, e, arr)
{
    // If there is one element in
    // array, store it in current
    // node of segment tree and return
    if (s == e) {
        st[node] = arr[s];
        return;
    }
    // If there are more than
    // one elements, then recur
    // for left and right subtrees
    // and store the max of
    // values in this node
    var mid = getMid(s, e);
 
    constructST(2 * node, s,
                mid, arr);
    constructST(2 * node + 1,
                mid + 1, e,
                arr);
    st[node] = Math.max(st[2 * node],
                   st[2 * node + 1]);
}
 
/* A recursive function to get the
   maximum of range[l, r] The
   following parameters for
   this function:
 
st     -> Pointer to segment tree
node   -> Index of current node in
          the segment tree .
s & e  -> Starting and ending indexes
          of the segment represented
          by current node, i.e., st[node]
l & r  -> Starting and ending indexes
          of range query
 */
function getMax(node, s, e, l, r)
{
    // If segment of this node
    // does not belong to
    // given range
    if (s > r || e < l)
        return -1000000000;
 
    // If segment of this node
    // is completely part of
    // given range, then return
    // the max of segment
    if (s >= l && e <= r)
        return st[node];
 
    // If segment of this node
    // is partially the part
    // of given range
    var mid = getMid(s, e);
 
    return Math.max(getMax(2 * node,
                      s, mid,
                      l, r),
               getMax(2 * node + 1,
                      mid + 1, e,
                      l, r));
}
 
// Function to print the max
// of all subarrays of size k
function printKMax(n, k)
{
    for (var i = 0; i < n; i++) {
        if ((k - 1 + i) < n)
            document.write( getMax(1, 0, n - 1,
                           i, k - 1 + i)
                 + " ");
        else
            break;
    }
}
 
// Driver code
var k = 4;
var arr = [8, 5, 10, 7, 9, 4, 15,
              12, 90, 13];
var n = arr.length;
// Function to construct the
// segment tree
constructST(1, 0, n - 1, arr);
printKMax(n, k);
 
 
</script>


Output: 

10 10 10 15 15 90 90

 

Time Complexity: O(N * log K)
Auxiliary Space: O(N * log K) 

Related Article: Sliding Window Maximum (Maximum of all subarrays of size k)
 Related Topic: Segment Tree



Last Updated : 28 Mar, 2023
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads