Find the number of sub arrays in the permutation of first N natural numbers such that their median is M

Given an array arr[] containing the permutation of first N natural numbers and an integer M ? N. The task is to find the number of sub-arrays such that the median of the sequence is M.Â
The median of a sequence is the value of the element which is in the middle of the sequence after sorting it in non-decreasing order. If the length of the sequence is even, the left of two middle elements is used.
Â
Examples:Â Â
Input: a[] = { 2, 4, 5, 3, 1}, M = 4Â
Output: 4Â
The required sub-arrays are {2, 4, 5}, {4}, {4, 5} and {4, 5, 3}.
ÂInput: a[] = { 1, 2, 3, 4, 5}, M = 5Â
Output: 1Â
Approach: The segment p[l..r] has a median equals M if and only if M belongs to it and less = greater or less = greater – 1, where less is the number of elements in p[l..r] that are strictly less than M and greater is a number of elements in p[l..r] that are strictly greater than M. Here we’ve used a fact that p is a permutation (on p[l..r] there is exactly one occurrence of M).
In other words, M belongs to p[l..r], and the value greater – less equals 0 or 1.
Calculate prefix sums sum[0..n], where sum[i] the value greater-less on the prefix of the length i (i.e., on the subarray p[0..i-1]). For the fixed value r it is easy to calculate the number of so l that p[l..r] is suitable. First, check that M met on [0..r]. Valid values l are such indices that: no M on [0..l-1] and sum[l]=sum[r] or sum[r]=sum[l]+1.
Let’s keep a number of prefix sums sum[i] to the left of M for each value. We can just use a map c, where c[s] is a number of indices l that sum[l]=s and l are to the left of m.
So, for each r that p[0..r] contains m do ans += c[sum] + c[sum – 1], where sum is the current value greater-less.
Below is the implementation of the above approach:
C++
// C++ implementation of the approach#include <bits/stdc++.h>using namespace std;Â
// Function to return the count of sub-arrays// in the given permutation of first n natural// numbers such that their median is mint segments(int n, int p[], int m){Â Â Â Â map<int, int> c;Â Â Â Â c[0] = 1;Â Â Â Â bool has = false;Â Â Â Â int sum = 0;Â Â Â Â long long ans = 0;Â Â Â Â for (int r = 0; r < n; r++) {Â
        // If element is less than m        if (p[r] < m)            sum--;Â
        // If element greater than m        else if (p[r] > m)            sum++;Â
        // If m is found        if (p[r] == m)            has = true;Â
        // Count the answer        if (has)            ans += c[sum] + c[sum - 1];Â
        // Increment sum        else            c[sum]++;    }Â
    return ans;}Â
// Driver codeint main(){Â Â Â Â int a[] = { 2, 4, 5, 3, 1 };Â Â Â Â int n = sizeof(a) / sizeof(a[0]);Â Â Â Â int m = 4;Â Â Â Â cout << segments(n, a, m);Â
    return 0;} |
Java
// Java implementation of the approach import java.util.HashMap;Â
class GFG {Â
    // Function to return the count of sub-arrays    // in the given permutation of first n natural    // numbers such that their median is m    public static int segments(int n, int[] p, int m)    {        HashMap<Integer, Integer> c = new HashMap<>();        c.put(0, 1);        boolean has = false;        int sum = 0;        int ans = 0;        for (int r = 0; r < n; r++)         {Â
            // If element is less than m            if (p[r] < m)                sum--;Â
            // If element greater than m            else if (p[r] > m)                sum++;Â
            // If m is found            if (p[r] == m)                has = true;Â
            // Count the answer            if (has)                ans += (c.get(sum) == null ? 0 :                         c.get(sum)) +                        (c.get(sum - 1) == null ? 0 :                         c.get(sum - 1));Â
            // Increment sum            else                c.put(sum, c.get(sum) == null ? 1 :                            c.get(sum) + 1);        }        return ans;    }Â
    // Driver code    public static void main(String[] args)     {        int[] a = { 2, 4, 5, 3, 1 };        int n = a.length;        int m = 4;        System.out.println(segments(n, a, m));    }}Â
// This code is contributed by// sanjeev2552 |
Python3
# Python3 implementation of the approachÂ
# Function to return the count of sub-arrays# in the given permutation of first n natural# numbers such that their median is mdef segments(n, p, m):Â
    c = dict()Â
    c[0] = 1Â
    has = FalseÂ
    Sum = 0Â
    ans = 0Â
    for r in range(n):Â
        # If element is less than m        if (p[r] < m):            Sum -= 1Â
        # If element greater than m        elif (p[r] > m):            Sum += 1Â
        # If m is found        if (p[r] == m):            has = TrueÂ
        # Count the answer        if (has):            if(Sum in c.keys()):                ans += c[Sum]            if Sum-1 in c.keys():                ans += c[Sum - 1] Â
        # Increment Sum        else:            c[Sum] = c.get(Sum, 0) + 1Â
    return ansÂ
# Driver codea = [2, 4, 5, 3, 1]n = len(a)m = 4print(segments(n, a, m))Â
# This code is contributed by mohit kumar |
C#
// C# implementation of the approach using System;using System.Collections.Generic;Â Â Â Â Â Â Â Â Â Â Â Â Â
class GFG {Â
    // Function to return the count of sub-arrays    // in the given permutation of first n natural    // numbers such that their median is m    public static int segments(int n, int[] p, int m)    {        Dictionary<int, int> c = new Dictionary<int, int>();        c.Add(0, 1);        bool has = false;        int sum = 0;        int ans = 0;        for (int r = 0; r < n; r++)         {Â
            // If element is less than m            if (p[r] < m)                sum--;Â
            // If element greater than m            else if (p[r] > m)                sum++;Â
            // If m is found            if (p[r] == m)                has = true;Â
            // Count the answer            if (has)                ans += (!c.ContainsKey(sum) ? 0 :                          c[sum]) +                     (!c.ContainsKey(sum - 1) ? 0 :                       c[sum - 1]);Â
            // Increment sum            else                c.Add(sum, !c.ContainsKey(sum) ? 1 :                             c[sum] + 1);        }        return ans;    }Â
    // Driver code    public static void Main(String[] args)     {        int[] a = { 2, 4, 5, 3, 1 };        int n = a.Length;        int m = 4;        Console.WriteLine(segments(n, a, m));    }}Â
// This code is contributed by 29AjayKumar |
PHP
<?php// PHP implementation of the approach Â
// Function to return the count of sub-arrays // in the given permutation of first n natural // numbers such that their median is m function segments($n, $p, $m) { Â Â Â Â $c = array(); Â Â Â Â $c[0] = 1; Â Â Â Â Â Â Â Â Â $has = false; Â Â Â Â $sum = 0; Â Â Â Â $ans = 0; Â Â Â Â Â Â Â Â Â for ($r = 0; $r < $n; $r++) Â Â Â Â { Â
        // If element is less than m         if ($p[$r] < $m)             $sum--; Â
        // If element greater than m         else if ($p[$r] > $m)             $sum++; Â
        // If m is found         if ($p[$r] == $m)             $has = true; Â
        // Count the answer         if ($has)             $ans += $c[$sum] + $c[$sum - 1]; Â
        // Increment sum         else            $c[$sum]++;     } Â
    return $ans; } Â
// Driver code $a = array( 2, 4, 5, 3, 1 ); $n = count($a);$m = 4; Â
echo segments($n, $a, $m); Â
// This code is contributed by Ryuga?> |
Javascript
<script>Â
// javascript implementation of the approachÂ
// Function to return the count of sub-arrays// in the given permutation of first n natural// numbers such that their median is mfunction segments(n, p, m){Â Â Â Â var c = new Map();Â Â Â Â c.set(0,1);Â Â Â Â var hs = false;Â Â Â Â var sum = 0;Â Â Â Â var ans = 0;Â Â Â Â var r;Â Â Â Â for (r = 0; r < n; r++) {Â
        // If element is less than m        if (p[r] < m)            sum--;Â
        // If element greater than m        else if (p[r] > m)            sum++;Â
        // If m is found        if (p[r] == m)            hs = true;Â
        // Count the answer        if (hs){            if(c.has(sum) && c.has(sum-1))              ans += c.get(sum) + c.get(sum - 1);            else if(c.has(sum))              ans += c.get(sum);            else if(c.has(sum-1))             ans += c.get(sum-1);        }Â
        // Increment sum        else{            if(c.has(sum))             c.set(sum,c.get(sum)+1);            else              c.set(sum,1);        }    }Â
    return ans;}Â
// Driver codeÂ
    var a = [2, 4, 5, 3, 1];    var n = a.length;    var m = 4;    document.write(segments(n, a, m));Â
</script> |
4
Â
Time Complexity: O(N)
Auxiliary Space: O(N)
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 zambiatek!



