Skip to content
Related Articles
Open in App
Not now

Related Articles

Check if Array elements of given range form a permutation

Improve Article
Save Article
  • Difficulty Level : Hard
  • Last Updated : 01 Dec, 2022
Improve Article
Save Article

Given an array arr[] consisting of N distinct integers and an array Q[][2] consisting of M queries of the form [L, R], the task for each query is to check if array elements over the range [L, R] forms a permutation or not.

Note: A permutation is a sequence of length N containing each number from 1 to N exactly once. For example, (1), (4,  3,  5,  1,  2) are permutations, and (1,  1), (4,  3,  1) are not.

Examples: 

Input: arr[] = {6, 4, 1, 2, 3, 5, 7}, Q[][] = {{2, 4}, {0, 4}, {1, 5}}
Output: 
YES
NO
YES
Explanation: Query 1: The elements of the array over the range [2, 4] are {1, 2, 3} which forms a permutation. Hence, print “YES”.
Query 2: The elements of the array over the range [0, 4] are {6, 4, 1, 2} which does not forms an permutation. Hence, print “NO”.
Query 3: The elements of the array over the range [1, 5] are {4, 1, 2, 3, 5}, which form an permutation. Hence, print “YES”.

Input: arr[] = {1, 2, 4, 3, 9}, Q[][] = {{0, 3}, {0, 4}}
Output: 
YES
NO

Naive Approach: The basic way to solve the problem is as follows:

Traverse the given array over the range [L, R] for each query and check if every element is present or not from 1 to R – L + 1. This can be done by taking the sum of all elements from L to R if it is equal to the sum of 1 + 2 + 3 + 4 + . . . . + size of subarray [L, R], then print “YES”. Otherwise, print “NO”.

Time Complexity: O(N * M)
Auxiliary Space: O(1)

Efficient Approach:  The above approach can be optimized based on the following idea:

The idea is rather than calculating the sum of elements from L to R for each query precomputation can be done using the prefix sum. For Each query Q sum from L to R can be found in O(1) time using prefix sum.

The sum from 1 + 2 + 3 + 4 + . . . + size of subarray [L, R] can be found using the number theory formula for finding the sum of the first n natural numbers which is n * (n + 1) / 2

Follow the steps below to solve the problem:

  • Initialize an array (say prefix[]) to store the prefix sum of the array 
  • To fill the prefix sum array, we run through index 1 to N and keep on adding the present element with the previous value in the prefix sum array.
  • Traverse the given array of queries Q[] and for each query {L, R}.
    • Initiate the size variable and fill with R – L + 1 which is the size of the subarray [L, R].
    • Initiate the total_From_1_To_Size variable whose value will fill with n * ( n + 1) / 2.
    • Initiate the variable total_From_L_To_R whose value will be found using precomputed array prefix[].
    • If total_From_L_To_R and total_From_1_To_Size are equal then print “YES” else print “NO“.

Below is the implementation of the above approach:

C++

// C++ code to implement the approach

#include <bits/stdc++.h>
using namespace std;

// Function to check if the given range
// of queries form an Permutation or not
// in the given array arr[]
void findPermutation(int arr[], int N,
                     int Q[][2], int M)
{
    // Precomputation array
    // stores the sum of all ranges
    // for any L to R
    int prefix[N + 1] = { 0 };

    // Iterates over the range [1, N]
    for (int i = 1; i <= N; i++) {

        // Finding prefix sum of
        // given array
        prefix[i] = prefix[i - 1] + arr[i - 1];
    }

    // Traverse the given queries
    for (int i = 0; i < M; i++) {

        // Stores range L to R for
        // each query
        int L = Q[i][0], R = Q[i][1];

        // Size variable stores size of
        // [L, R] range
        int size = R - L + 1;

        // Stores total from 1 to size of
        // range [L, R]
        int total_From_1_To_Size
            = size * (size + 1) / 2;

        // Stores total sum from L to R
        // of Array
        int total_From_L_To_R
            = prefix[R] - prefix[L - 1];

        // If total from 1 to size is equal
        // to total from L to R then print
        // yes
        if (total_From_L_To_R == total_From_1_To_Size) {
            cout << "YES" << endl;
        }
        else {
            cout << "NO" << endl;
        }
    }
}

// Driver Code
int main()
{
    int arr[] = { 6, 4, 1, 2, 3, 5, 7 };
    int Q[][2] = { { 3, 5 }, { 1, 5 }, { 2, 6 } };
    int N = sizeof(arr) / sizeof(arr[0]);
    int M = sizeof(Q) / sizeof(Q[0]);

    // Function Call
    findPermutation(arr, N, Q, M);

    return 0;
}

Java

// Java code to implement the approach
import java.io.*;

class GFG {
    // Function to check if the given range
    // of queries form an Permutation or not
    // in the given array arr[]
    public static void findPermutation(int arr[], int N,
                                       int Q[][], int M)
    {
        // Precomputation array
        // stores the sum of all ranges
        // for any L to R
        int prefix[] = new int[N + 1];

        // Iterates over the range [1, N]
        for (int i = 1; i <= N; i++) {

            // Finding prefix sum of
            // given array
            prefix[i] = prefix[i - 1] + arr[i - 1];
        }

        // Traverse the given queries
        for (int i = 0; i < M; i++) {

            // Stores range L to R for
            // each query
            int L = Q[i][0], R = Q[i][1];

            // Size variable stores size of
            // [L, R] range
            int size = R - L + 1;

            // Stores total from 1 to size of
            // range [L, R]
            int total_From_1_To_Size
                = size * (size + 1) / 2;

            // Stores total sum from L to R
            // of Array
            int total_From_L_To_R
                = prefix[R] - prefix[L - 1];

            // If total from 1 to size is equal
            // to total from L to R then print
            // yes
            if (total_From_L_To_R == total_From_1_To_Size) {
                System.out.println("YES");
            }
            else {
                System.out.println("NO");
            }
        }
    }

    // Driver Code
    public static void main(String[] args)
    {
        int arr[] = { 6, 4, 1, 2, 3, 5, 7 };
        int Q[][] = { { 3, 5 }, { 1, 5 }, { 2, 6 } };
        int N = arr.length;
        int M = Q.length;

        // Function Call
        findPermutation(arr, N, Q, M);
    }
}

// This code is contributed by Rohit Pradhan

Python3

# Python code to implement the approach

# Function to check if the given range
# of queries form an Permutation or not
# in the given array arr[]
def findPermutation(arr, N, Q, M) :

    # Precomputation array
    # stores the sum of all ranges
    # for any L to R
    prefix = [0] * (N + 1)

    # Iterates over the range [1, N]
    for i in range(1, N+1):

        # Finding prefix sum of
        # given array
        prefix[i] = prefix[i - 1] + arr[i - 1]
    

    # Traverse the given queries
    for i in range(0, M):

        # Stores range L to R for
        # each query
        L = Q[i][0]
        R = Q[i][1]

        # Size variable stores size of
        # [L, R] range
        size = R - L + 1

        # Stores total from 1 to size of
        # range [L, R]
        total_From_1_To_Size = size * (size + 1) // 2

        # Stores total sum from L to R
        # of Array
        total_From_L_To_R = prefix[R] - prefix[L - 1]

        # If total from 1 to size is equal
        # to total from L to R then print
        # yes
        if (total_From_L_To_R == total_From_1_To_Size) :
            print("YES")
        
        else :
            print("NO")
        
# Driver Code
if __name__ == "__main__":

    arr = [ 6, 4, 1, 2, 3, 5, 7 ]
    Q = [[ 3, 5 ], [ 1, 5 ], [ 2, 6]]  
    N = len(arr) 
    M = len(Q) 

    # Function Call
    findPermutation(arr, N, Q, M)
    
    # This code is contributed by sanjoy_62.

C#

// C# code to implement the approach

using System;

public class GFG {

    // Function to check if the given range
    // of queries form an Permutation or not
    // in the given array arr[]
    public static void findPermutation(int[] arr, int N,
                                       int[, ] Q, int M)
    {
        // Precomputation array
        // stores the sum of all ranges
        // for any L to R
        int[] prefix = new int[N + 1];

        // Iterates over the range [1, N]
        for (int i = 1; i <= N; i++) {

            // Finding prefix sum of
            // given array
            prefix[i] = prefix[i - 1] + arr[i - 1];
        }

        // Traverse the given queries
        for (int i = 0; i < M; i++) {

            // Stores range L to R for
            // each query
            int L = Q[i, 0], R = Q[i, 1];

            // Size variable stores size of
            // [L, R] range
            int size = R - L + 1;

            // Stores total from 1 to size of
            // range [L, R]
            int total_From_1_To_Size
                = size * (size + 1) / 2;

            // Stores total sum from L to R
            // of Array
            int total_From_L_To_R
                = prefix[R] - prefix[L - 1];

            // If total from 1 to size is equal
            // to total from L to R then print
            // yes
            if (total_From_L_To_R == total_From_1_To_Size) {
                Console.WriteLine("YES");
            }
            else {
                Console.WriteLine("NO");
            }
        }
    }

    static public void Main()
    {

        // Code
        int[] arr = { 6, 4, 1, 2, 3, 5, 7 };
        int[, ] Q = { { 3, 5 }, { 1, 5 }, { 2, 6 } };
        int N = arr.Length;
        int M = Q.GetLength(0);

        // Function Call
        findPermutation(arr, N, Q, M);
    }
}

// This code is contributed by lokeshmvs21.

Javascript

        // JavaScript code to implement the approach

        // Function to check if the given range
        // of queries form an Permutation or not
        // in the given array arr[]
        const findPermutation = (arr, N, Q, M) => {
            // Precomputation array
            // stores the sum of all ranges
            // for any L to R
            let prefix = new Array(N + 1).fill(0);

            // Iterates over the range [1, N]
            for (let i = 1; i <= N; i++) {

                // Finding prefix sum of
                // given array
                prefix[i] = prefix[i - 1] + arr[i - 1];
            }

            // Traverse the given queries
            for (let i = 0; i < M; i++) {

                // Stores range L to R for
                // each query
                let L = Q[i][0], R = Q[i][1];

                // Size variable stores size of
                // [L, R] range
                let size = R - L + 1;

                // Stores total from 1 to size of
                // range [L, R]
                let total_From_1_To_Size
                    = size * parseInt((size + 1) / 2);

                // Stores total sum from L to R
                // of Array
                let total_From_L_To_R
                    = prefix[R] - prefix[L - 1];

                // If total from 1 to size is equal
                // to total from L to R then print
                // yes
                if (total_From_L_To_R == total_From_1_To_Size) {
                    console.log("YES<br/>");
                }
                else {
                    console.log("NO<br/>");
                }
            }
        }

        // Driver Code

        let arr = [6, 4, 1, 2, 3, 5, 7];
        let Q = [[3, 5], [1, 5], [2, 6]];
        let N = arr.length;
        let M = Q.length;

        // Function Call
        findPermutation(arr, N, Q, M);

        // This code is contributed by rakeshsahni
Output

YES
NO
YES

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


My Personal Notes arrow_drop_up
Related Articles

Start Your Coding Journey Now!