📌  相关文章
📜  求数组中三元组的最大总和,例如 i < j < k 和 a[i] < a[j] < a[k]

📅  最后修改于: 2022-05-13 01:57:53.006000             🧑  作者: Mango

求数组中三元组的最大总和,例如 i < j < k 和 a[i] < a[j] < a[k]

给定一个大小为 n 的正整数数组。求三元组 ( a i + a j + a k ) 的最大和,使得 0 <= i < j < k < n 和a i < a j < a k

Input: a[] = 2 5 3 1 4 9
Output: 16

Explanation:
All possible triplets are:-
2 3 4 => sum = 9
2 5 9 => sum = 16
2 3 9 => sum = 14
3 4 9 => sum = 16
1 4 9 => sum = 14
Maximum sum = 16

简单的方法是用三个嵌套的“for循环”遍历每个三元组,并找到一个一个更新所有三元组的总和。这种方法的时间复杂度是 O(n 3 ),对于较大的“n”值是不够的。

更好的方法是在上述方法中进一步优化。我们可以遍历两个嵌套循环,而不是通过三个嵌套循环遍历每个三元组。在遍历每个数字时(假设为中间元素(a j )),找到小于它前面的j的最大数字(a i )和大于它后面的j的最大数字(a k )。之后,用计算出的 a i + a j + a k之和更新最大答案

C++
// C++ program to find maximum triplet sum
#include 
using namespace std;
 
// Function to calculate maximum triplet sum
int maxTripletSum(int arr[], int n)
{
    // Initialize the answer
    int ans = 0;
 
    for (int i = 1; i < n - 1; ++i) {
        int max1 = 0, max2 = 0;
 
        // find maximum value(less than arr[i])
        // from 0 to i-1
        for (int j = 0; j < i; ++j)
            if (arr[j] < arr[i])
                max1 = max(max1, arr[j]);
 
        // find maximum value(greater than arr[i])
        // from i+1 to n-1
        for (int j = i + 1; j < n; ++j)
            if (arr[j] > arr[i])
                max2 = max(max2, arr[j]);
 
        // store maximum answer
        if(max1 && max2)
             ans=max(ans,max1+arr[i]+max2);
    }
 
    return ans;
}
 
// Driver code
int main()
{
    int arr[] = { 2, 5, 3, 1, 4, 9 };
    int n = sizeof(arr) / sizeof(arr[0]);
    cout << maxTripletSum(arr, n);
    return 0;
}


Java
// Java program to find maximum triplet sum
 
import java.io.*;
import java.math.*;
 
class GFG {
 
    // Function to calculate maximum triplet sum
    static int maxTripletSum(int arr[], int n)
    {
        // Initialize the answer
        int ans = 0;
 
        for (int i = 1; i < n - 1; ++i) {
            int max1 = 0, max2 = 0;
 
            // find maximum value(less than arr[i])
            // from 0 to i-1
            for (int j = 0; j < i; ++j)
                if (arr[j] < arr[i])
                    max1 = Math.max(max1, arr[j]);
 
            // find maximum value(greater than arr[i])
            // from i+1 to n-1
            for (int j = i + 1; j < n; ++j)
                if (arr[j] > arr[i])
                    max2 = Math.max(max2, arr[j]);
 
            // store maximum answer
        if(max1 > 0 && max2 > 0)
            ans = Math.max(ans, max1 + arr[i] + max2);
        }
 
        return ans;
    }
 
    // Driver code
    public static void main(String args[])
    {
        int arr[] = { 2, 5, 3, 1, 4, 9 };
        int n = arr.length;
        System.out.println(maxTripletSum(arr, n));
    }
}
 
// This code is contributed by Nikita Tiwari.


Python3
# Python 3 program to
# find maximum triplet sum
 
# Function to calculate
# maximum triplet sum
 
 
def maxTripletSum(arr, n):
 
    # Initialize the answer
    ans = 0
 
    for i in range(1, (n - 1)):
        max1 = 0
        max2 = 0
 
        # find maximum value(less than arr[i])
        # from 0 to i-1
        for j in range(0, i):
            if (arr[j] < arr[i]):
                max1 = max(max1, arr[j])
 
        # find maximum value(greater than arr[i])
        # from i + 1 to n-1
        for j in range((i + 1), n):
            if (arr[j] > arr[i]):
                max2 = max(max2, arr[j])
 
        # store maximum answer
                if (max1 > 0 and max2 >0):
                    ans = max(ans, max1 + arr[i] + max2)
 
    return ans
 
 
# Driver code
 
arr = [2, 5, 3, 1, 4, 9]
n = len(arr)
print(maxTripletSum(arr, n))
 
 
# This code is contributed
# by Nikita Tiwari.


C#
// C# program to find maximum triplet sum
using System;
 
class GFG {
 
    // Function to calculate maximum triplet sum
    static int maxTripletSum(int[] arr, int n)
    {
         
        // Initialize the answer
        int ans = 0;
 
        for (int i = 1; i < n - 1; ++i)
        {
            int max1 = 0, max2 = 0;
 
            // find maximum value(less than
            // arr[i]) from 0 to i-1
            for (int j = 0; j < i; ++j)
                if (arr[j] < arr[i])
                    max1 = Math.Max(max1, arr[j]);
 
            // find maximum value(greater than
            // arr[i]) from i+1 to n-1
            for (int j = i + 1; j < n; ++j)
                if (arr[j] > arr[i])
                    max2 = Math.Max(max2, arr[j]);
 
            // store maximum answer
        if(max1 > 0 && max2 > 0)
            ans = Math.Max(ans, max1 + arr[i] + max2);
        }
 
        return ans;
    }
 
    // Driver code
    public static void Main()
    {
         
        int[] arr = { 2, 5, 3, 1, 4, 9 };
        int n = arr.Length;
         
        Console.WriteLine(maxTripletSum(arr, n));
    }
}
 
// This code is contributed by vt_m.


PHP
 $arr[$i])
                $max2 = max($max2, $arr[$j]);
 
        // store maximum answer
        if($max1 && $max2)
             $ans = max($ans, $max1 + $arr[$i] + $max2);
    }
 
    return $ans;
}
 
    // Driver code
    $arr = array(2, 5, 3, 1, 4, 9);
    $n = sizeof($arr);
    echo maxTripletSum($arr, $n);
 
// This code is contributed by nitin mittal.
?>


Javascript


C++
// C++ program to find maximum triplet sum
#include 
using namespace std;
 
// Utility function to get the lower last min
// value of 'n'
int getLowValue(set& lowValue, int& n)
{
    auto it = lowValue.lower_bound(n);
 
    // Since 'lower_bound' returns the first
    // iterator greater than 'n', thus we
    // have to decrement the pointer for
    // getting the minimum value
    --it;
 
    return (*it);
}
 
// Function to calculate maximum triplet sum
int maxTripletSum(int arr[], int n)
{
    // Initialize suffix-array
    int maxSuffArr[n + 1];
 
    // Set the last element
    maxSuffArr[n] = 0;
 
    // Calculate suffix-array containing maximum
    // value for index i, i+1, i+2, ... n-1 in
    // arr[i]
    for (int i = n - 1; i >= 0; --i)
        maxSuffArr[i] = max(maxSuffArr[i + 1], arr[i]);
 
    int ans = 0;
 
    // Initialize set container
    set lowValue;
 
    // Insert minimum value for first comparison
    // in the set
    lowValue.insert(INT_MIN);
 
    for (int i = 0; i < n - 1; ++i) {
        if (maxSuffArr[i + 1] > arr[i]) {
            ans = max(ans, getLowValue(lowValue,
                                       arr[i])
                               + arr[i] + maxSuffArr[i + 1]);
 
            // Insert arr[i] in set<> for further
            // processing
            lowValue.insert(arr[i]);
        }
    }
    return ans;
}
 
// Driver code
int main()
{
    int arr[] = { 2, 5, 3, 1, 4, 9 };
    int n = sizeof(arr) / sizeof(arr[0]);
 
    cout << maxTripletSum(arr, n);
    return 0;
}


Java
// Java program to find maximum triplet sum
import java.io.*;
import java.util.*;
 
class GFG{
     
// Function to calculate maximum triplet sum
public static int maxTripletSum(int arr[], int n)
{
     
    // Initialize suffix-array
    int maxSuffArr[] = new int[n + 1];
 
    // Set the last element
    maxSuffArr[n] = 0;
 
    // Calculate suffix-array containing maximum
    // value for index i, i+1, i+2, ... n-1 in
    // arr[i]
    for(int i = n - 1; i >= 0; --i)
        maxSuffArr[i] = Math.max(maxSuffArr[i + 1],
                                        arr[i]);
 
    int ans = 0;
 
    // Initialize set container
    TreeSet lowValue = new TreeSet();
 
    // Insert minimum value for first comparison
    // in the set
    lowValue.add(Integer.MIN_VALUE);
 
    for(int i = 0; i < n - 1; ++i)
    {
        if (maxSuffArr[i + 1] > arr[i])
        {
            ans = Math.max(ans, lowValue.lower(arr[i]) +
                           arr[i] + maxSuffArr[i + 1]);
 
            // Insert arr[i] in set<> for further
            // processing
            lowValue.add(arr[i]);
        }
    }
    return ans;
}
 
// Driver Code
public static void main(String[] args)
{
    int arr[] = { 2, 5, 3, 1, 4, 9 };
    int n = 6;
     
    System.out.println(maxTripletSum(arr, n));
}
}
 
// This code is contributed by Manu Pathria


输出 :

16

时间复杂度: O(n 2 )
辅助空间: O(1)

最好和有效的方法是使用最大后缀数组和二进制搜索的概念。

  • 为了找到一个大于给定数字的最大数字,我们可以维护一个最大后缀数组,这样对于任何数字(后缀i )它都将包含索引 i、i+1、... n-1 中的最大数字。后缀数组可以在 O(n) 时间内计算出来。
  • 为了找到小于它前面给定数字的最大数字,我们可以在给定数字之前维护一个排序的数字列表,这样我们就可以简单地执行二进制搜索来找到一个刚好小于给定数字的数字。在 C++ 语言中,我们可以通过使用 STL 库的集合关联容器来执行此操作。

C++

// C++ program to find maximum triplet sum
#include 
using namespace std;
 
// Utility function to get the lower last min
// value of 'n'
int getLowValue(set& lowValue, int& n)
{
    auto it = lowValue.lower_bound(n);
 
    // Since 'lower_bound' returns the first
    // iterator greater than 'n', thus we
    // have to decrement the pointer for
    // getting the minimum value
    --it;
 
    return (*it);
}
 
// Function to calculate maximum triplet sum
int maxTripletSum(int arr[], int n)
{
    // Initialize suffix-array
    int maxSuffArr[n + 1];
 
    // Set the last element
    maxSuffArr[n] = 0;
 
    // Calculate suffix-array containing maximum
    // value for index i, i+1, i+2, ... n-1 in
    // arr[i]
    for (int i = n - 1; i >= 0; --i)
        maxSuffArr[i] = max(maxSuffArr[i + 1], arr[i]);
 
    int ans = 0;
 
    // Initialize set container
    set lowValue;
 
    // Insert minimum value for first comparison
    // in the set
    lowValue.insert(INT_MIN);
 
    for (int i = 0; i < n - 1; ++i) {
        if (maxSuffArr[i + 1] > arr[i]) {
            ans = max(ans, getLowValue(lowValue,
                                       arr[i])
                               + arr[i] + maxSuffArr[i + 1]);
 
            // Insert arr[i] in set<> for further
            // processing
            lowValue.insert(arr[i]);
        }
    }
    return ans;
}
 
// Driver code
int main()
{
    int arr[] = { 2, 5, 3, 1, 4, 9 };
    int n = sizeof(arr) / sizeof(arr[0]);
 
    cout << maxTripletSum(arr, n);
    return 0;
}

Java

// Java program to find maximum triplet sum
import java.io.*;
import java.util.*;
 
class GFG{
     
// Function to calculate maximum triplet sum
public static int maxTripletSum(int arr[], int n)
{
     
    // Initialize suffix-array
    int maxSuffArr[] = new int[n + 1];
 
    // Set the last element
    maxSuffArr[n] = 0;
 
    // Calculate suffix-array containing maximum
    // value for index i, i+1, i+2, ... n-1 in
    // arr[i]
    for(int i = n - 1; i >= 0; --i)
        maxSuffArr[i] = Math.max(maxSuffArr[i + 1],
                                        arr[i]);
 
    int ans = 0;
 
    // Initialize set container
    TreeSet lowValue = new TreeSet();
 
    // Insert minimum value for first comparison
    // in the set
    lowValue.add(Integer.MIN_VALUE);
 
    for(int i = 0; i < n - 1; ++i)
    {
        if (maxSuffArr[i + 1] > arr[i])
        {
            ans = Math.max(ans, lowValue.lower(arr[i]) +
                           arr[i] + maxSuffArr[i + 1]);
 
            // Insert arr[i] in set<> for further
            // processing
            lowValue.add(arr[i]);
        }
    }
    return ans;
}
 
// Driver Code
public static void main(String[] args)
{
    int arr[] = { 2, 5, 3, 1, 4, 9 };
    int n = 6;
     
    System.out.println(maxTripletSum(arr, n));
}
}
 
// This code is contributed by Manu Pathria

输出:

16

时间复杂度: O(n*log(n))
辅助空间: O(n)