Given a permutation P of first N natural numbers, the task is to count the index pairs (i, j) such that P[i] + P[j] = max(P[x]) where i ? x ? j.
Examples:
Input: P[] = {3, 4, 1, 5, 2}
Output: 2
Only valid index pairs are (0, 4) and (0, 2)
Input: P[] = {1, 3, 2}
Output: 1
Naive approach: We can solve this problem by iterating for all possible pairs (i, j) and each time gets maximum between them. The time complexity of this approach will be O(n3).
Efficient Approach: Fix the maximum element on a segment and iterate on either the elements to the left of it or to the right of it. If the current maximum is x, and the element we found is y then check whether element x-y can form a subsegment with y (i.e. x is the maximum value on the segment between y and x-y). This works in O(n*n)
But if we can precompute the borders of the segments where x is the maximum element and always choose to iterate on the smaller part of the segment then time complexity will reduce to O(nlogn).
Because every element will be processed no more than logn times, if we process it in a segment of size m, the smaller part of it contains no more than m/2 elements ( which we will process later, and the smaller part of this segment contains no more than m/4 elements, and so on..).
Below is the implementation of the above approach:
// CPP implementation of the approach #include<bits/stdc++.h> using namespace std;
// Function to return the count of // required index pairs int Count_Segment( int p[], int n)
{ // To store the required count
int count = 0;
// Array to store the left elements
// upto which current element is maximum
int upto[n + 1];
for ( int i = 0; i < n + 1; i++)
upto[i] = 0;
// Iterating through the whole permutation
// except first and last element
int j = 0,curr = 0;
for ( int i = 1; i < n + 1; i++)
{
// If current element can be maximum
// in a subsegment
if (p[i] > p[i - 1] and p[i] > p[i + 1])
{
// Current maximum
curr = p[i];
// Iterating for smaller values then
// current maximum on left of it
j = i - 1;
while (j >= 0 and p[j] < curr)
{
// Storing left borders
// of the current maximum
upto[p[j]]= curr;
j -= 1;
}
// Iterating for smaller values then
// current maximum on right of it
j = i + 1;
while (j < n and p[j] < curr)
{
// Condition satisfies
if (upto[curr-p[j]] == curr)
count += 1;
j+= 1;
}
}
}
// Return count of subsegments
return count;
} // Driver Code int main()
{ int p[] = {3, 4, 1, 5, 2};
int n = sizeof (p)/ sizeof (p[0]);
cout << (Count_Segment(p, n));
return 0;
} // This code is contributed by // Surendra_Gangwar |
// Java implementation of the approach import java.util.*;
class GFG
{ // Function to return the count of // required index pairs static int Count_Segment( int p[], int n)
{ // To store the required count
int count = 0 ;
// Array to store the left elements
// upto which current element is maximum
int []upto = new int [n + 1 ];
for ( int i = 0 ; i < n + 1 ; i++)
upto[i] = 0 ;
// Iterating through the whole permutation
// except first and last element
int j = 0 ,curr = 0 ;
for ( int i = 1 ; i < n ; i++)
{
// If current element can be maximum
// in a subsegment
if (p[i] > p[i - 1 ] && p[i] > p[i + 1 ])
{
// Current maximum
curr = p[i];
// Iterating for smaller values then
// current maximum on left of it
j = i - 1 ;
while (j >= 0 && p[j] < curr)
{
// Storing left borders
// of the current maximum
upto[p[j]]= curr;
j -= 1 ;
}
// Iterating for smaller values then
// current maximum on right of it
j = i + 1 ;
while (j < n && p[j] < curr)
{
// Condition satisfies
if (upto[curr-p[j]] == curr)
count += 1 ;
j+= 1 ;
}
}
}
// Return count of subsegments
return count;
} // Driver Code public static void main(String[] args)
{ int p[] = { 3 , 4 , 1 , 5 , 2 };
int n = p.length;
System.out.println(Count_Segment(p, n));
} } /* This code contributed by PrinciRaj1992 */ |
# Python3 implementation of the approach # Function to return the count of # required index pairs def Count_Segment(p, n):
# To store the required count
count = 0
# Array to store the left elements
# upto which current element is maximum
upto = [ False ] * (n + 1 )
# Iterating through the whole permutation
# except first and last element
for i in range ( 1 , n - 1 ):
# If current element can be maximum
# in a subsegment
if p[i]>p[i - 1 ] and p[i]>p[i + 1 ]:
# Current maximum
curr = p[i]
# Iterating for smaller values then
# current maximum on left of it
j = i - 1
while j> = 0 and p[j]<curr:
# Storing left borders
# of the current maximum
upto[p[j]] = curr
j - = 1
# Iterating for smaller values then
# current maximum on right of it
j = i + 1
while j<n and p[j]<curr:
# Condition satisfies
if upto[curr - p[j]] = = curr:
count + = 1
j + = 1
# Return count of subsegments
return count
# Driver Code if __name__ = = "__main__" :
p = [ 3 , 4 , 1 , 5 , 2 ]
n = len (p)
print (Count_Segment(p, n))
|
// C# implementation of the approach using System;
class GFG
{ // Function to return the count of // required index pairs static int Count_Segment( int []p, int n)
{ // To store the required count
int count = 0;
// Array to store the left elements
// upto which current element is maximum
int []upto = new int [n + 1];
for ( int i = 0; i < n + 1; i++)
upto[i] = 0;
// Iterating through the whole permutation
// except first and last element
int j = 0,curr = 0;
for ( int i = 1; i < n ; i++)
{
// If current element can be maximum
// in a subsegment
if (p[i] > p[i - 1] && p[i] > p[i + 1])
{
// Current maximum
curr = p[i];
// Iterating for smaller values then
// current maximum on left of it
j = i - 1;
while (j >= 0 && p[j] < curr)
{
// Storing left borders
// of the current maximum
upto[p[j]]= curr;
j= j - 1;
}
// Iterating for smaller values then
// current maximum on right of it
j = i + 1;
while (j < n && p[j] < curr)
{
// Condition satisfies
if (upto[curr-p[j]] == curr)
count += 1;
j= j+ 1;
}
}
}
// Return count of subsegments
return count;
} // Driver Code static public void Main ()
{ int []p = {3, 4, 1, 5, 2};
int n = p.Length;
Console.WriteLine(Count_Segment(p, n));
} } /* This code contributed by ajit*/ |
<script> // javascript implementation of the approach // Function to return the count of
// required index pairs
function Count_Segment(p , n) {
// To store the required count
var count = 0;
// Array to store the left elements
// upto which current element is maximum
var upto = Array(n + 1).fill(0);
for (i = 0; i < n + 1; i++)
upto[i] = 0;
// Iterating through the whole permutation
// except first and last element
var j = 0, curr = 0;
for (i = 1; i < n; i++) {
// If current element can be maximum
// in a subsegment
if (p[i] > p[i - 1] && p[i] > p[i + 1]) {
// Current maximum
curr = p[i];
// Iterating for smaller values then
// current maximum on left of it
j = i - 1;
while (j >= 0 && p[j] < curr) {
// Storing left borders
// of the current maximum
upto[p[j]] = curr;
j -= 1;
}
// Iterating for smaller values then
// current maximum on right of it
j = i + 1;
while (j < n && p[j] < curr) {
// Condition satisfies
if (upto[curr - p[j]] == curr)
count += 1;
j += 1;
}
}
}
// Return count of subsegments
return count;
}
// Driver Code
var p = [ 3, 4, 1, 5, 2 ];
var n = p.length;
document.write(Count_Segment(p, n));
// This code is contributed by todaysgaurav </script> |
2
Time Complexity: O(N2), where N represents the size of the given array.
Auxiliary Space: O(N), where N represents the size of the given array.