📜  计算满足给定条件的索引对

📅  最后修改于: 2021-05-06 09:09:48             🧑  作者: Mango

给定前N个自然数的排列P ,任务是对索引对(i,j)进行计数使得P [i] + P [j] = max(P [x]) ,其中i≤x≤j

例子:

天真的方法:我们可以通过迭代所有可能的对(i,j)来解决此问题,并且每次在它们之间获得最大值。该方法的时间复杂度将为O(n 3 )

高效的方法:将最大元素固定在一个线段上,然后对其左侧或右侧的元素进行迭代。如果当前最大值是x,而我们找到的元素是y,则检查元素xy是否可以与y形成子段(即x是分段上的最大值)
在y和xy之间)。这适用于O(n * n)
但是,如果我们可以预先计算x为最大元素的段的边界,并且始终选择对段的较小部分进行迭代,则时间复杂度将降低为O(nlogn)。
因为每个元素的处理时间都不会超过logn次,所以如果我们在大小为m的段中对其进行处理,则它的较小部分将包含不超过m / 2个元素(稍后我们将对其进行处理,而该段的较小部分最多包含m / 4个元素,依此类推..)。

下面是上述方法的实现:

C++
// CPP implementation of the approach
#include
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
// 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 */


Python
# 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]


C#
// 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*/


输出:
2