📌  相关文章
📜  数组的所有可能子数组的最大元素的总和

📅  最后修改于: 2021-04-26 05:06:17             🧑  作者: Mango

给定一个数组arr [] ,任务是找到该数组的每个可能子数组的最大元素之和。

例子:

一种简单的方法是生成所有子数组,然后将所有子数组中的最大元素求和。该解决方案的时间复杂度将为O(n 3 )。

更好的方法:
优化的关键是问题-

我们可能想到的下一个想法是针对数组arr中的每个索引i ,我们尝试找到:
左数:我们向索引i的左侧进行迭代,直到没有遇到严格大于arr [i]的元素,或者没有到达数组的左端。让我们将给定数组的索引i的此计数称为CLi
正确的计数:我们朝索引的右边进行迭代,直到没有遇到大于或等于索引值的元素,或者没有到达正确的末端。让我们将给定数组的索引i的此计数称为CRi

(CLi + 1)*(CRi + 1)将是当前索引i的子数组数量,其值将为最大值,因为有CLi + 1种从左侧选择元素的方式(包括不选择任何元素)和CRi + 1从右侧选择元素的方法。

最佳方法:
使用O(n)时间的堆栈数据结构可以解决此问题。这个想法与以前的方法相同。为了节省时间,我们将使用C++标准模板库中的堆栈。

剩余计数:CLi代表索引i的剩余计数。索引i的CLi可以定义为索引i和最右边的元素之间的元素数量,这些元素的值严格大于arr [i]且索引小于i 。如果没有这样的元素,则元素的CLi等于索引i左侧的元素数。

为此,我们将只从左到右插入元素的索引到堆栈中。让我们假设,我们正在堆栈中插入索引i ,而j是堆栈中当前存在的最顶层元素的索引。当值arr [i]大于或等于堆栈中最顶层索引的值并且堆栈不为空时,请继续弹出堆栈中的元素。每当弹出元素时,当前索引(i)的左计数(CLi)都会更新为CLi = CLi + CLj + 1

正确计数:我们以类似方式计算所有索引的正确计数。唯一的区别是我们在数组中从右到左遍历时将元素推入堆栈。尽管arr [i]严格大于堆栈中最顶部索引的值,并且堆栈不为空,但请继续弹出元素。每当弹出一个元素时,当前索引(i)的正确计数就会更新为CRi = CRi + CRj + 1

最后一步:ans为包含最终答案的变量。我们将其初始化为0 。然后,我们将通过所有的索引进行迭代从1到所述阵列的n和从1更新ANSANS = ANS +(CLI + 1)*(CRI + 1)* ARR [I]对于i的所有可能值以n

下面是上述方法的实现:

C++
// C++ implementation of the approach
#include 
#include 
using namespace std;
  
// Function to return the required sum
int findMaxSum(int arr[], int n)
{
    // Arrays for maintaining left and right count
    int CL[n] = { 0 }, CR[n] = { 0 };
  
    // Stack for storing the indexes
    stack q;
  
    // Calculate left count for every index
    for (int i = 0; i < n; i++) {
        while (q.size() != 0 && arr[q.top()] <= arr[i]) {
            CL[i] += CL[q.top()] + 1;
            q.pop();
        }
        q.push(i);
    }
  
    // Clear the stack
    while (q.size() != 0)
        q.pop();
  
    // Calculate right count for every index
    for (int i = n - 1; i >= 0; i--) {
        while (q.size() != 0 && arr[q.top()] < arr[i]) {
            CR[i] += CR[q.top()] + 1;
            q.pop();
        }
        q.push(i);
    }
  
    // Clear the stack
    while (q.size() != 0)
        q.pop();
  
    // To store the required sum
    int ans = 0;
  
    // Calculate the final sum
    for (int i = 0; i < n; i++)
        ans += (CL[i] + 1) * (CR[i] + 1) * arr[i];
  
    return ans;
}
  
// Driver code
int main()
{
    int arr[] = { 1, 3, 2 };
    int n = sizeof(arr) / sizeof(arr[0]);
    cout << findMaxSum(arr, n);
}


Java
// Java implementation of the above approach 
import java.util.*; 
  
public class GFG 
{ 
    // Function to return the required sum 
    static int findMaxSum(int arr[], int n) 
    { 
        // Arrays for maintaining left and right count 
        int CL[] = new int[n], CR[] = new int[n]; 
      
        // Stack for storing the indexes 
        Stack q = new Stack(); 
      
        // Calculate left count for every index 
        for (int i = 0; i < n; i++) 
        { 
            while (q.size() != 0 && arr[q.peek()] <= arr[i]) 
            { 
                CL[i] += CL[q.peek()] + 1; 
                q.pop(); 
            } 
            q.push(i); 
        } 
      
        // Clear the stack 
        while (q.size() != 0) 
            q.pop(); 
      
        // Calculate right count for every index 
        for (int i = n - 1; i >= 0; i--) 
        { 
            while (q.size() != 0 && arr[q.peek()] < arr[i]) 
            { 
                CR[i] += CR[q.peek()] + 1; 
                q.pop(); 
            } 
            q.push(i); 
        } 
      
        // Clear the stack 
        while (q.size() != 0) 
            q.pop(); 
      
        // To store the required sum 
        int ans = 0; 
      
        // Calculate the final sum 
        for (int i = 0; i < n; i++) 
            ans += (CL[i] + 1) * (CR[i] + 1) * arr[i]; 
      
        return ans; 
    } 
  
    // Driver code 
    public static void main(String[] args) 
    { 
        int arr[] = { 1, 3, 2 }; 
        int n = arr.length; 
        System.out.println(findMaxSum(arr, n)); 
    } 
} 
  
// This code is contributed by Rituraj Jain


Python3
# Python3 implementation of the approach 
  
# Function to return the required sum 
def findMinSum(arr, n): 
  
    # Arrays for maintaining left 
    # and right count 
    CL = [0] * n
    CR = [0] * n 
  
    # Stack for storing the indexes 
    q = []
  
    # Calculate left count for every index 
    for i in range(0, n): 
        while (len(q) != 0 and
               arr[q[-1]] <= arr[i]): 
            CL[i] += CL[q[-1]] + 1
            q.pop() 
          
        q.append(i) 
  
    # Clear the stack 
    while len(q) != 0: 
        q.pop() 
  
    # Calculate right count for every index 
    for i in range(n - 1, -1, -1): 
        while (len(q) != 0 and 
               arr[q[-1]] < arr[i]): 
            CR[i] += CR[q[-1]] + 1
            q.pop() 
          
        q.append(i) 
  
    # Clear the stack 
    while len(q) != 0: 
        q.pop() 
  
    # To store the required sum 
    ans = 0
  
    # Calculate the final sum 
    for i in range(0, n): 
        ans += (CL[i] + 1) * (CR[i] + 1) * arr[i] 
  
    return ans 
  
# Driver code 
if __name__ == "__main__":
  
    arr = [1, 3, 2] 
    n = len(arr) 
    print(findMinSum(arr, n))
      
# This code is contributed by Rituraj Jain


C#
// C# implementation of the above approach 
using System;
using System.Collections.Generic;
      
class GFG 
{ 
    // Function to return the required sum 
    static int findMaxSum(int []arr, int n) 
    { 
        // Arrays for maintaining left and right count 
        int []CL = new int[n]; int []CR = new int[n]; 
      
        // Stack for storing the indexes 
        Stack q = new Stack(); 
      
        // Calculate left count for every index 
        for (int i = 0; i < n; i++) 
        { 
            while (q.Count != 0 && arr[q.Peek()] <= arr[i]) 
            { 
                CL[i] += CL[q.Peek()] + 1; 
                q.Pop(); 
            } 
            q.Push(i); 
        } 
      
        // Clear the stack 
        while (q.Count != 0) 
            q.Pop(); 
      
        // Calculate right count for every index 
        for (int i = n - 1; i >= 0; i--) 
        { 
            while (q.Count != 0 && arr[q.Peek()] < arr[i]) 
            { 
                CR[i] += CR[q.Peek()] + 1; 
                q.Pop(); 
            } 
            q.Push(i); 
        } 
      
        // Clear the stack 
        while (q.Count != 0) 
            q.Pop(); 
      
        // To store the required sum 
        int ans = 0; 
      
        // Calculate the final sum 
        for (int i = 0; i < n; i++) 
            ans += (CL[i] + 1) * (CR[i] + 1) * arr[i]; 
      
        return ans; 
    } 
  
    // Driver code 
    public static void Main(String[] args) 
    { 
        int []arr = { 1, 3, 2 }; 
        int n = arr.Length; 
        Console.WriteLine(findMaxSum(arr, n)); 
    } 
} 
  
// This code has been contributed by 29AjayKumar


输出:
15

时间复杂度: O(n)

想要从精选的最佳视频中学习并解决问题,请查看有关从基础到高级C++的C++基础课程以及有关语言和STL的C++ STL课程。要完成从学习语言到DS Algo等的更多准备工作,请参阅“完整面试准备课程”