Open In App

Queries on Left and Right Circular shift on array

Improve
Improve
Improve
Like Article
Like
Save Article
Save
Share
Report issue
Report

Given an array arr[] of N integers. There are three types of commands: 

  • 1 x: Right Circular Shift the array x times. If an array is a[0], a[1], …., a[n – 1], then after one right circular shift the array will become a[n – 1], a[0], a[1], …., a[n – 2].
  • 2 y: Left Circular Shift the array y times. If an array is a[0], a[1], …., a[n – 1], then after one left circular shift the array will become a[1], …., a[n – 2], a[n – 1], a[0].
  • 3 l r: Print the sum of all integers in the subarray a[l…r] (l and r inclusive).

Given Q queries, the task is to execute each query.

Examples:

Input: N = 5, arr[] = { 1, 2, 3, 4, 5 },
query 1 = { 1, 3 }
query 2 = { 3, 0, 2 }
query 3 = { 2, 1 }
query 4 = { 3, 1, 4 }
Output: 12,11
Explanation: Initial array arr[] = { 1, 2, 3, 4, 5 } 
After query 1, arr[] = { 3, 4, 5, 1, 2 }
After query 2, sum from index 0 to index 2 is 12, 
So output 12.
After query 3, arr[] = { 4, 5, 1, 2, 3 }
After query 4, sum from index 1 to index 4 is 11. 
So output 11.

Input: N = 5, arr[] = { 1, 2, 3, 4, 5 }
query 1 = { 2, 1 }
query 2 = { 3, 0, 2 }
query 3 = { 1, 3 }
query 4 = { 3, 1, 4 }
Output: 9, 11 
Explanation:
Initial array arr[] = { 1, 2, 3, 4, 5 } 
After query 1, arr[] = {2, 3, 4, 5, 1 }
After query 2, sum from index 0 to index 2 is 9. 
So output 9.
After query 3, arr[] = { 4, 5, 1, 2, 3}
After query 4, sum from index 1 to index 4 is 11. 
So output 11.

Approach 1 (Brute Approach): The basic idea is as follows:

For each type of query, perform the mentioned task. In each query either do left rotation, or right rotation or find the sum of the elements in the given range.

Time Complexity: O(N * Q) where Q is the number of queries.
Auxiliary Space: O(1)

Approach 2 (Efficient Approach): The approach is based on the concept of prefix sum and array rotation as follows:

Initially the array is not rotated. So, calculate the net rotation of the array. A negative net rotation means right rotation and positive net rotation means left rotation. Whenever there is a query asking for the sum of a range provide the sum of the elements that will be in that range after the net rotation till that index.

Follow the below steps to implement the idea:

  • Calculate the prefix sum of the given array.
  • We just need to track the net rotation. 
    • If the tracked number is negative, It means left rotation has dominated else right rotation has dominated. 
    • When tracking the net rotations, calculate the net rotation mod N
  • If there is a need to answer any query of a third type and the boundaries are l and r
    • Find what l and r were in the original order. 
    • We can easily find it out by adding the net rotations to the index and taking mod N
    • Use the prefix sum array to find the sum of the given range in constant time.

Follow the below illustration for a better understanding:

Illustration:

Initial array arr[] = { 1, 2, 3, 4, 5 } and the queries are
query 1 = {2, 1}
query 2 = {3, 0, 2}
query 3 = {1, 3}
query 4 = {3, 1, 4}

The prefixsum[] = { 1, 3, 6, 10, 15 } 

query 1 = {2, 1}: 
        => Net rotation = 1

query 2 = { 3, 0, 2 }: 
        => Net rotation = 1
        => Say l = 0, r = 2.
        => Value of l in original order = 1 and r in original order = 3.
        => Therefore, the sum = 10 – 1 = 9.

query 3 = {1, 3}:
        => Net rotation = 1 – 3 = -2

query 4 = {3, 1, 4}:
        => Net rotation = -2
        => Say l = 1, r = 4.
        => Value of l in original order = (1 – 2 + 5)%5 = 4
        => Value of r in original order = (4 – 2 + 5)%5 = 2
        => The sum = (15 – 10) + 6 = 11

Below is the implementation of the above approach:  

C++




// C++ Program to solve queries on Left and Right
// Circular shift on array
#include <bits/stdc++.h>
using namespace std;
 
// Function to solve query of type 1 x.
void querytype1(int* toRotate, int times, int n)
{
    // Decreasing the absolute rotation
    (*toRotate) = ((*toRotate) - times) % n;
}
 
// Function to solve query of type 2 y.
void querytype2(int* toRotate, int times, int n)
{
    // Increasing the absolute rotation.
    (*toRotate) = ((*toRotate) + times) % n;
}
 
// Function to solve queries of type 3 l r.
void querytype3(int toRotate, int l, int r, int preSum[],
                int n)
{
    // Finding absolute l and r.
    l = (l + toRotate + n) % n;
    r = (r + toRotate + n) % n;
 
    // if l is before r.
    if (l <= r)
        cout << (preSum[r + 1] - preSum[l]) << endl;
 
    // If r is before l.
    else
        cout << (preSum[n] + preSum[r + 1] - preSum[l])
             << endl;
}
 
// Wrapper Function solve all queries.
void wrapper(int a[], int n)
{
    int preSum[n + 1];
    preSum[0] = 0;
 
    // Finding Prefix sum
    for (int i = 1; i <= n; i++)
        preSum[i] = preSum[i - 1] + a[i - 1];
 
    int toRotate = 0;
 
    // Solving each query
    querytype1(&toRotate, 3, n);
    querytype3(toRotate, 0, 2, preSum, n);
    querytype2(&toRotate, 1, n);
    querytype3(toRotate, 1, 4, preSum, n);
}
 
// Driver Program
int main()
{
    int arr[] = { 1, 2, 3, 4, 5 };
    int N = sizeof(arr) / sizeof(arr[0]);
    wrapper(arr, N);
    return 0;
}


Java




// Java Program to solve queries on Left and Right
// Circular shift on array
import java.io.*;
 
class GFG {
 
    // Function to solve query of type 1 x.
    static int querytype1(int toRotate, int times, int n)
    {
 
        // Decreasing the absolute rotation
        toRotate = (toRotate - times) % n;
        return toRotate;
    }
 
    // Function to solve query of type 2 y.
    static int querytype2(int toRotate, int times, int n)
    {
        // Increasing the absolute rotation.
        toRotate = (toRotate + times) % n;
        return toRotate;
    }
 
    // Function to solve queries of type 3 l r.
    static void querytype3(int toRotate, int l, int r,
                           int preSum[], int n)
    {
        // Finding absolute l and r.
        l = (l + toRotate + n) % n;
        r = (r + toRotate + n) % n;
 
        // if l is before r.
        if (l <= r)
            System.out.println(preSum[r + 1] - preSum[l]);
 
        // If r is before l.
        else
            System.out.println(preSum[n] + preSum[r + 1]
                               - preSum[l]);
    }
 
    // Wrapper Function solve all queries.
    static void wrapper(int a[], int n)
    {
        int preSum[] = new int[n + 1];
        preSum[0] = 0;
 
        // Finding Prefix sum
        for (int i = 1; i <= n; i++)
            preSum[i] = preSum[i - 1] + a[i - 1];
 
        int toRotate = 0;
 
        // Solving each query
        toRotate = querytype1(toRotate, 3, n);
        querytype3(toRotate, 0, 2, preSum, n);
        toRotate = querytype2(toRotate, 1, n);
        querytype3(toRotate, 1, 4, preSum, n);
    }
 
    // Driver Program
    public static void main(String args[])
    {
        int arr[] = { 1, 2, 3, 4, 5 };
        int N = arr.length;
        wrapper(arr, N);
    }
}
 
// This code is contributed by saurabh_jaiswal.


Python3




# Python Program to solve queries on Left and Right
# Circular shift on array
 
# Function to solve query of type 1 x.
def querytype1(toRotate, times, n):
   
    # Decreasing the absolute rotation
    toRotate = (toRotate - times) % n
    return toRotate
 
# Function to solve query of type 2 y.
def querytype2(toRotate, times, n):
   
    # Increasing the absolute rotation.
    toRotate = (toRotate + times) % n
    return toRotate
 
# Function to solve queries of type 3 l r.
def querytype3( toRotate, l, r, preSum, n):
   
    # Finding absolute l and r.
    l = (l + toRotate + n) % n
    r = (r + toRotate + n) % n
 
    # if l is before r.
    if (l <= r):
        print((preSum[r + 1] - preSum[l]))  
 
    # If r is before l.
    else:
        print((preSum[n] + preSum[r + 1] - preSum[l]))
 
# Wrapper Function solve all queries.
def wrapper( a, n):
    preSum = [ 0 for i in range(n + 1)]
     
    # Finding Prefix sum
    for i in range(1,n+1):
        preSum[i] = preSum[i - 1] + a[i - 1]
 
    toRotate = 0
 
    # Solving each query
    toRotate = querytype1(toRotate, 3, n)
    querytype3(toRotate, 0, 2, preSum, n)
    toRotate = querytype2(toRotate, 1, n)
    querytype3(toRotate, 1, 4, preSum, n);
 
# Driver Program
if __name__ == '__main__':
    arr = [ 1, 2, 3, 4, 5 ]
    N = len(arr)
    wrapper(arr, N)
 
# This code is contributed by rohan07.


C#




// C# Program to solve queries on Left and Right
// Circular shift on array
using System;
class GFG {
 
    // Function to solve query of type 1 x.
    static int querytype1(int toRotate, int times, int n)
    {
 
        // Decreasing the absolute rotation
        toRotate = (toRotate - times) % n;
        return toRotate;
    }
 
    // Function to solve query of type 2 y.
    static int querytype2(int toRotate, int times, int n)
    {
        // Increasing the absolute rotation.
        toRotate = (toRotate + times) % n;
        return toRotate;
    }
 
    // Function to solve queries of type 3 l r.
    static void querytype3(int toRotate, int l, int r,
                           int[] preSum, int n)
    {
        // Finding absolute l and r.
        l = (l + toRotate + n) % n;
        r = (r + toRotate + n) % n;
 
        // if l is before r.
        if (l <= r)
            Console.WriteLine(preSum[r + 1] - preSum[l]);
 
        // If r is before l.
        else
            Console.WriteLine(preSum[n] + preSum[r + 1]
                              - preSum[l]);
    }
 
    // Wrapper Function solve all queries.
    static void wrapper(int[] a, int n)
    {
        int[] preSum = new int[n + 1];
        preSum[0] = 0;
 
        // Finding Prefix sum
        for (int i = 1; i <= n; i++)
            preSum[i] = preSum[i - 1] + a[i - 1];
 
        int toRotate = 0;
 
        // Solving each query
        toRotate = querytype1(toRotate, 3, n);
        querytype3(toRotate, 0, 2, preSum, n);
        toRotate = querytype2(toRotate, 1, n);
        querytype3(toRotate, 1, 4, preSum, n);
    }
 
    // Driver Program
    public static void Main()
    {
        int[] arr = { 1, 2, 3, 4, 5 };
        int N = arr.Length;
        wrapper(arr, N);
    }
}
 
// This code is contributed by _saurabh_jaiswal


Javascript




<script>
 
// JavaScript Program to solve queries on Left and Right
// Circular shift on array
 
// Function to solve query of type 1 x.
function querytype1(toRotate, times, n){
 
    // Decreasing the absolute rotation
    toRotate = (toRotate - times) % n
    return toRotate
}
 
// Function to solve query of type 2 y.
function querytype2(toRotate, times, n){
 
    // Increasing the absolute rotation.
    toRotate = (toRotate + times) % n
    return toRotate
}
 
// Function to solve queries of type 3 l r.
function querytype3( toRotate, l, r, preSum, n){
 
    // Finding absolute l and r.
    l = (l + toRotate + n) % n
    r = (r + toRotate + n) % n
 
    // if l is before r.
    if (l <= r)
        document.write((preSum[r + 1] - preSum[l]),"</br>")
 
    // If r is before l.
    else
        document.write((preSum[n] + preSum[r + 1] - preSum[l]),"</br>")
}
 
// Wrapper Function solve all queries.
function wrapper(a, n){
    preSum = new Array(n+1).fill(0)
 
    // Finding Prefix sum
    for(let i = 1; i <= n; i++)
        preSum[i] = preSum[i - 1] + a[i - 1]
 
    toRotate = 0
 
    // Solving each query
    toRotate = querytype1(toRotate, 3, n)
    querytype3(toRotate, 0, 2, preSum, n)
    toRotate = querytype2(toRotate, 1, n)
    querytype3(toRotate, 1, 4, preSum, n);
}
 
// Driver Program
let arr = [ 1, 2, 3, 4, 5 ]
let N = arr.length
wrapper(arr, N)
 
// This code is contributed by rohan07.
</script>


Output

12
11

Time Complexity: O(N)
Auxiliary Space: O(N)



Last Updated : 09 Dec, 2022
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads