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

📅  最后修改于: 2021-09-08 13:45:54             🧑  作者: 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*/


Javascript


输出:
2

如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程学生竞争性编程现场课程