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

📅  最后修改于: 2021-05-04 07:20: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 findMinSum(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 << findMinSum(arr, n);
}


Java
// Java implementation of the above approach 
import java.util.*;
  
class GFG 
{
  
// Function to return the required sum
static int findMinSum(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(findMinSum(arr, n));
}
}
  
// This code is contributed by Rajput-Ji


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 findMinSum(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(findMinSum(arr, n));
}
}
  
// This code has been contributed
// by 29AjayKumar


输出:
10

时间复杂度: O(n)

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