Queries to find maximum sum contiguous subarrays of given length in a rotating array

Given an array arr[] of N integers and Q queries of the form {X, Y} of the following two types:

  • If X = 1, rotate the given array to the left by Y positions.
  • If X = 2, print the maximum sum subarray of length Y in the current state of the array.

Examples: 

Input: N = 5, arr[] = {1, 2, 3, 4, 5}, Q = 2, Query[][] = {{1, 2}, {2, 3}}
Output:
Query 1: 3 4 5 1 2
Query 2: 12
Explanation:
Query 1: Shift array to the left 2 times: {1, 2, 3, 4, 5} -> {2, 3, 4, 5, 1} -> {3, 4, 5, 1, 2}
Query 2: Maximum sum subarray of length 3 is {3, 4, 5} and the sum is 12

Input: N = 5, arr[] = {3, 4, 5, 1, 2}, Q = 3, Query[][] = {{1, 3}, {1, 1}, {2, 4}}
Output: 
Query 1: 1 2 3 4 5
Query 2: 2 3 4 5 1
Query 3: 14
Explanation:
Query 1: Shift array to the left 3 times: {3, 4, 5, 1, 2} -> {4, 5, 1, 2, 3} -> {5, 1, 2, 3, 4} -> {1, 2, 3, 4, 5}
Query 2: Shift array to the left 1 time: {1, 2, 3, 4, 5} -> {2, 3, 4, 5, 1}
Query 3: Maximum sum subarray of length 4 is {2, 3, 4, 5} and sum is 14

Naive Approach: The simplest approach is to rotate the array by shifting elements one by one up to distance Y for queries is of type 1 and generating the sum of all the subarrays of length Y and print the maximum sum if the query is of type 2



Time Complexity: O(Q*N*Y)
Auxiliary Space: O(N)

Efficient Approach: To optimize the above approach, the idea is to use the Juggling Algorithm for array rotation and for finding the maximum sum subarray of length Y, use the Sliding Window Technique. Follow the steps below to solve the problem:

  1. If X = 1, rotate the array by Y, using the Juggling Algorithm.
  2. Otherwise, if X = 2, find the maximum sum subarray of length Y using the Sliding Window Technique.
  3. Print the array if query X is 1.
  4. Otherwise, print the maximum sum subarray of size Y.

Below is the implementation of the above approach:

C++

filter_none

edit
close

play_arrow

link
brightness_4
code

// C++ program for the above approach
  
#include <bits/stdc++.h>
using namespace std;
  
// Function to calculate the maximum
// sum of length k
int MaxSum(vector<int> arr, int n,
           int k)
{
    int i, max_sum = 0, sum = 0;
  
    // Calculating the max sum for
    // the first k elements
    for (i = 0; i < k; i++) {
        sum += arr[i];
    }
    max_sum = sum;
  
    // Find subarray with maximum sum
    while (i < n) {
  
        // Update the sum
        sum = sum - arr[i - k] + arr[i];
        if (max_sum < sum) {
            max_sum = sum;
        }
        i++;
    }
  
    // Return maximum sum
    return max_sum;
}
  
// Function to calculate gcd of the
// two numbers n1 and n2
int gcd(int n1, int n2)
{
    // Base Case
    if (n2 == 0) {
        return n1;
    }
  
    // Recursively find the GCD
    else {
        return gcd(n2, n1 % n2);
    }
}
  
// Function to rotate the array by Y
vector<int> RotateArr(vector<int> arr,
                      int n, int d)
{
    // For handling k >= N
    int i = 0, j = 0;
    d = d % n;
  
    // Dividing the array into
    // number of sets
    int no_of_sets = gcd(d, n);
  
    for (i = 0; i < no_of_sets; i++) {
  
        int temp = arr[i];
        j = i;
  
        // Rotate the array by Y
        while (true) {
  
            int k = j + d;
  
            if (k >= n)
                k = k - n;
  
            if (k == i)
                break;
  
            arr[j] = arr[k];
            j = k;
        }
  
        // Update arr[j]
        arr[j] = temp;
    }
  
    // Return the rotated array
    return arr;
}
  
// Function that performs the queries
// on the given array
void performQuery(vector<int>& arr,
                  int Q[][2], int q)
{
  
    int N = (int)arr.size();
  
    // Traverse each query
    for (int i = 0; i < q; i++) {
  
        // If query of type X = 1
        if (Q[i][0] == 1) {
  
            arr = RotateArr(arr, N,
                            Q[i][1]);
  
            // Print the array
            for (auto t : arr) {
                cout << t << " ";
            }
            cout << "\n";
        }
  
        // If query of type X = 2
        else {
            cout << MaxSum(arr, N, Q[i][1])
                 << "\n";
        }
    }
}
  
// Driver Code
int main()
{
    // Given array arr[]
    vector<int> arr = { 1, 2, 3, 4, 5 };
  
    int q = 5;
  
    // Given Queries
    int Q[][2] = { { 1, 2 }, { 2, 3 }, 
                   { 1, 3 }, { 1, 1 }, 
                   { 2, 4 }
    };
  
    // Function Call
    performQuery(arr, Q, q);
  
    return 0;
}

chevron_right


Java

filter_none

edit
close

play_arrow

link
brightness_4
code

// Java program for 
// the above approach
class GFG{
  
// Function to calculate the maximum
// sum of length k
static int MaxSum(int []arr, 
                  int n, int k)
{
  int i, max_sum = 0, sum = 0;
  
  // Calculating the max sum for
  // the first k elements
  for (i = 0; i < k; i++) 
  {
    sum += arr[i];
  }
  max_sum = sum;
  
  // Find subarray with maximum sum
  while (i < n) 
  {
    // Update the sum
    sum = sum - arr[i - k] +
                arr[i];
    if (max_sum < sum) 
    {
      max_sum = sum;
    }
    i++;
  }
  
  // Return maximum sum
  return max_sum;
}
  
// Function to calculate gcd 
//  of the two numbers n1 and n2
static int gcd(int n1, int n2)
{
  // Base Case
  if (n2 == 0
  {
    return n1;
  }
  
  // Recursively find the GCD
  else 
  {
    return gcd(n2, n1 % n2);
  }
}
  
// Function to rotate the array by Y
static int []RotateArr(int []arr,
                       int n, int d)
{
  // For handling k >= N
  int i = 0, j = 0;
  d = d % n;
  
  // Dividing the array into
  // number of sets
  int no_of_sets = gcd(d, n);
  
  for (i = 0; i < no_of_sets; i++) 
  {
    int temp = arr[i];
    j = i;
  
    // Rotate the array by Y
    while (true
    {
      int k = j + d;
  
      if (k >= n)
        k = k - n;
  
      if (k == i)
        break;
  
      arr[j] = arr[k];
      j = k;
    }
  
    // Update arr[j]
    arr[j] = temp;
  }
  
  // Return the rotated array
  return arr;
}
  
// Function that performs the queries
// on the given array
static void performQuery(int []arr,
                         int Q[][], int q)
{
  int N = arr.length;
  
  // Traverse each query
  for (int i = 0; i < q; i++) 
  {
    // If query of type X = 1
    if (Q[i][0] == 1
    {
      arr = RotateArr(arr, N,
                      Q[i][1]);
  
      // Print the array
      for (int t : arr) 
      {
        System.out.print(t + " ");
      }
      System.out.print("\n");
    }
  
    // If query of type X = 2
    else 
    {
      System.out.print(MaxSum(arr, N, 
                              Q[i][1]) + "\n");
    }
  }
}
  
// Driver Code
public static void main(String[] args)
{
  // Given array arr[]
  int []arr = {1, 2, 3, 4, 5};
  
  int q = 5;
  
  // Given Queries
  int Q[][] = {{1, 2}, {2, 3}, 
               {1, 3}, {1, 1}, 
               {2, 4}};
  
  // Function Call
  performQuery(arr, Q, q);
}
}
  
// This code is contributed by Rajput-Ji

chevron_right


Python3

filter_none

edit
close

play_arrow

link
brightness_4
code

# Python3 program for the above approach
  
# Function to calculate the maximum
# sum of length k
def MaxSum(arr, n, k):
      
    i, max_sum = 0, 0
    sum = 0
  
    # Calculating the max sum for
    # the first k elements
    while i < k:
        sum += arr[i]
        i += 1
          
    max_sum = sum
  
    # Find subarray with maximum sum
    while (i < n):
  
        # Update the sum
        sum = sum - arr[i - k] + arr[i]
          
        if (max_sum < sum):
            max_sum = sum
              
        i += 1
  
    # Return maximum sum
    return max_sum
  
# Function to calculate gcd of the
# two numbers n1 and n2
def gcd(n1, n2):
      
    # Base Case
    if (n2 == 0):
        return n1
  
    # Recursively find the GCD
    else:
        return gcd(n2, n1 % n2)
  
# Function to rotate the array by Y
def RotateArr(arr, n, d):
      
    # For handling k >= N
    i = 0
    j = 0
    d = d % n
  
    # Dividing the array into
    # number of sets
    no_of_sets = gcd(d, n)
  
    for i in range(no_of_sets):
        temp = arr[i]
        j = i
  
        # Rotate the array by Y
        while (True):
            k = j + d
  
            if (k >= n):
                k = k - n
            if (k == i):
                break
  
            arr[j] = arr[k]
            j = k
  
        # Update arr[j]
        arr[j] = temp
  
    # Return the rotated array
    return arr
  
# Function that performs the queries
# on the given array
def performQuery(arr, Q, q):
  
    N = len(arr)
  
    # Traverse each query
    for i in range(q):
  
        # If query of type X = 1
        if (Q[i][0] == 1):
            arr = RotateArr(arr, N, Q[i][1])
  
            # Print the array
            for t in arr:
                print(t, end = " ")
                  
            print()
  
        # If query of type X = 2
        else:
            print(MaxSum(arr, N, Q[i][1]))
  
# Driver Code
if __name__ == '__main__':
      
    # Given array arr[]
    arr = [ 1, 2, 3, 4, 5 ]
  
    q = 5
  
    # Given Queries
    Q = [ [ 1, 2 ], [ 2, 3 ],
          [ 1, 3 ], [ 1, 1 ],
          [ 2, 4 ] ]
  
    # Function call
    performQuery(arr, Q, q)
  
# This code is contributed by mohit kumar 29

chevron_right


C#

filter_none

edit
close

play_arrow

link
brightness_4
code

// C# program for the above approach
using System;
class GFG{
      
// Function to calculate the maximum
// sum of length k
static int MaxSum(int[] arr, int n, 
                             int k)
{
    int i, max_sum = 0, sum = 0;
      
    // Calculating the max sum for
    // the first k elements
    for(i = 0; i < k; i++) 
    {
        sum += arr[i];
    }
    max_sum = sum;
      
    // Find subarray with maximum sum
    while (i < n) 
    {
          
        // Update the sum
        sum = sum - arr[i - k] +
                    arr[i];
                      
        if (max_sum < sum) 
        {
            max_sum = sum;
        }
        i++;
    }
      
    // Return maximum sum
    return max_sum;
}
   
// Function to calculate gcd 
//  of the two numbers n1 and n2
static int gcd(int n1, int n2)
{
      
    // Base Case
    if (n2 == 0) 
    {
        return n1;
    }
      
    // Recursively find the GCD
    else
    {
        return gcd(n2, n1 % n2);
    }
}
   
// Function to rotate the array by Y
static int []RotateArr(int []arr, int n,
                                  int d)
{
      
    // For handling k >= N
    int i = 0, j = 0;
    d = d % n;
      
    // Dividing the array into
    // number of sets
    int no_of_sets = gcd(d, n);
      
    for(i = 0; i < no_of_sets; i++) 
    {
        int temp = arr[i];
        j = i;
          
        // Rotate the array by Y
        while (true
        {
            int k = j + d;
              
            if (k >= n)
                k = k - n;
              
            if (k == i)
                break;
              
            arr[j] = arr[k];
            j = k;
        }
          
        // Update arr[j]
        arr[j] = temp;
    }
      
    // Return the rotated array
    return arr;
}
  
// Function that performs the queries
// on the given array
static void performQuery(int[] arr,
                         int[,] Q, int q)
{
    int N = arr.Length;
      
    // Traverse each query
    for(int i = 0; i < q; i++) 
    {
          
        // If query of type X = 1
        if (Q[i, 0] == 1) 
        {
            arr = RotateArr(arr, N,
                            Q[i, 1]);
          
            // Print the array
            for(int t = 0; t < arr.Length; t++) 
            {
                Console.Write(arr[t] + " ");
            }
            Console.WriteLine();
        }
      
        // If query of type X = 2
        else
        {
            Console.WriteLine(MaxSum(arr, N,
                                     Q[i, 1]));
        }
    }
}
  
// Driver code
static void Main()
{
      
    // Given array arr[]
    int[] arr = { 1, 2, 3, 4, 5 };
      
    int q = 5;
      
    // Given Queries
    int[,] Q = { { 1, 2 }, { 2, 3 }, 
                 { 1, 3 }, { 1, 1 }, 
                 { 2, 4 } };
      
    // Function call
    performQuery(arr, Q, q);
}
}
  
// This code is contributed by divyeshrabadiya07

chevron_right


Output: 

3 4 5 1 2 
12
1 2 3 4 5 
2 3 4 5 1 
14

Time Complexity: O(Q*N), where Q is the number of queries, and N is the size of the given array.
Auxiliary Space: O(N)

Attention reader! Don’t stop learning now. Get hold of all the important DSA concepts with the DSA Self Paced Course at a student-friendly price and become industry ready.




My Personal Notes arrow_drop_up

DSC Lead at Google Developer Clubs

If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please Improve this article if you find anything incorrect by clicking on the "Improve Article" button below.