给定一个由N个整数组成的数组a [] ,任务是找到可以通过从子数组的所有元素中减去任意值(例如X)来实现的最大和。
例子:
Input: N = 3, a[] = {80, 48, 82}
Output: 144
Explanation:
48 can be deducted from each array element. Therefore, sum obtained = 48 * 3 = 144
Input: N = a[] = {8, 40, 77}
Output: 80
Explanation:
Subtracting 8 from all array elements generates sum 24.
Subtracting 40 from arr[1] and arr[2] generates sum 80.
Subtracting 77 from arr[2] generates sum 77.
Therefore, maximum possible sum is 80.
方法:
请按照以下步骤解决问题:
- 遍历数组
- 对于每一个元素,发现这是最近在其左侧小,其右侧最接近的较小的元素。
- 通过该元素计算current_element *(j – i – 1)来计算可能的总和,其中j和i分别是左侧和右侧最接近的较小数字的索引。
- 在所有这些中找到最大可能的和。
下面是上述方法的实现:
C++
// C++ program to implement
// the above approach
#include
using namespace std;
// Function to generate previous smaller
// element for each array element
vector findPrevious(vector a, int n)
{
vector ps(n);
// The first element has no
// previous smaller
ps[0] = -1;
// Stack to keep track of elements
// that have occurred previously
stack Stack;
// Push the first index
Stack.push(0);
for(int i = 1; i < n; i++)
{
// Pop all the elements until the previous
// element is smaller than current element
while (Stack.size() > 0 &&
a[Stack.top()] >= a[i])
Stack.pop();
// Store the previous smaller element
ps[i] = Stack.size() > 0 ?
Stack.top() : -1;
// Push the index of the current element
Stack.push(i);
}
// Return the array
return ps;
}
// Function to generate next smaller element
// for each array element
vector findNext(vector a, int n)
{
vector ns(n);
ns[n - 1] = n;
// Stack to keep track of elements
// that have occurring next
stack Stack;
Stack.push(n - 1);
// Iterate in reverse order
// for calculating next smaller
for(int i = n - 2; i >= 0; i--)
{
// Pop all the elements until the
// next element is smaller
// than current element
while (Stack.size() > 0 &&
a[Stack.top()] >= a[i])
Stack.pop();
// Store the next smaller element
ns[i] = Stack.size() > 0 ?
Stack.top() : n;
// Push the index of the current element
Stack.push(i);
}
// Return the array
return ns;
}
// Function to find the maximum sum by
// subtracting same value from all
// elements of a Subarray
int findMaximumSum(vector a, int n)
{
// Stores previous smaller element
vector prev_smaller = findPrevious(a, n);
// Stores next smaller element
vector next_smaller = findNext(a, n);
int max_value = 0;
for(int i = 0; i < n; i++)
{
// Calculate contribution
// of each element
max_value = max(max_value, a[i] *
(next_smaller[i] -
prev_smaller[i] - 1));
}
// Return answer
return max_value;
}
// Driver Code
int main()
{
int n = 3;
vector a{ 80, 48, 82 };
cout << findMaximumSum(a, n);
return 0;
}
// This code is contributed by divyeshrabadiya07
Java
// Java Program to implement
// the above approach
import java.util.*;
public class GFG {
// Function to find the maximum sum by
// subtracting same value from all
// elements of a Subarray
public static int findMaximumSum(int[] a, int n)
{
// Stores previous smaller element
int prev_smaller[] = findPrevious(a, n);
// Stores next smaller element
int next_smaller[] = findNext(a, n);
int max_value = 0;
for (int i = 0; i < n; i++) {
// Calculate contribution
// of each element
max_value
= Math.max(max_value,
a[i] * (next_smaller[i]
- prev_smaller[i] - 1));
}
// Return answer
return max_value;
}
// Function to generate previous smaller element
// for each array element
public static int[] findPrevious(int[] a, int n)
{
int ps[] = new int[n];
// The first element has no
// previous smaller
ps[0] = -1;
// Stack to keep track of elements
// that have occurred previously
Stack stack = new Stack<>();
// Push the first index
stack.push(0);
for (int i = 1; i < a.length; i++) {
// Pop all the elements until the previous
// element is smaller than current element
while (stack.size() > 0
&& a[stack.peek()] >= a[i])
stack.pop();
// Store the previous smaller element
ps[i] = stack.size() > 0 ? stack.peek() : -1;
// Push the index of the current element
stack.push(i);
}
// Return the array
return ps;
}
// Function to generate next smaller element
// for each array element
public static int[] findNext(int[] a, int n)
{
int ns[] = new int[n];
ns[n - 1] = n;
// Stack to keep track of elements
// that have occurring next
Stack stack = new Stack<>();
stack.push(n - 1);
// Iterate in reverse order
// for calculating next smaller
for (int i = n - 2; i >= 0; i--) {
// Pop all the elements until the
// next element is smaller
// than current element
while (stack.size() > 0
&& a[stack.peek()] >= a[i])
stack.pop();
// Store the next smaller element
ns[i] = stack.size() > 0 ? stack.peek()
: a.length;
// Push the index of the current element
stack.push(i);
}
// Return the array
return ns;
}
// Driver Code
public static void main(String args[])
{
int n = 3;
int a[] = { 80, 48, 82 };
System.out.println(findMaximumSum(a, n));
}
}
Python3
# Python3 program to implement
# the above approach
# Function to find the maximum sum by
# subtracting same value from all
# elements of a Subarray
def findMaximumSum(a, n):
# Stores previous smaller element
prev_smaller = findPrevious(a, n)
# Stores next smaller element
next_smaller = findNext(a, n)
max_value = 0
for i in range(n):
# Calculate contribution
# of each element
max_value = max(max_value, a[i] *
(next_smaller[i] -
prev_smaller[i] - 1))
# Return answer
return max_value
# Function to generate previous smaller
# element for each array element
def findPrevious(a, n):
ps = [0] * n
# The first element has no
# previous smaller
ps[0] = -1
# Stack to keep track of elements
# that have occurred previously
stack = []
# Push the first index
stack.append(0)
for i in range(1, n):
# Pop all the elements until the previous
# element is smaller than current element
while len(stack) > 0 and a[stack[-1]] >= a[i]:
stack.pop()
# Store the previous smaller element
ps[i] = stack[-1] if len(stack) > 0 else -1
# Push the index of the current element
stack.append(i)
# Return the array
return ps
# Function to generate next smaller
# element for each array element
def findNext(a, n):
ns = [0] * n
ns[n - 1] = n
# Stack to keep track of elements
# that have occurring next
stack = []
stack.append(n - 1)
# Iterate in reverse order
# for calculating next smaller
for i in range(n - 2, -1, -1):
# Pop all the elements until the
# next element is smaller
# than current element
while (len(stack) > 0 and
a[stack[-1]] >= a[i]):
stack.pop()
# Store the next smaller element
ns[i] = stack[-1] if len(stack) > 0 else n
# Push the index of the current element
stack.append(i)
# Return the array
return ns
# Driver code
n = 3
a = [ 80, 48, 82 ]
print(findMaximumSum(a, n))
# This code is contributed by Stuti Pathak
C#
// C# Program to implement
// the above approach
using System;
using System.Collections.Generic;
class GFG{
// Function to find the maximum sum by
// subtracting same value from all
// elements of a Subarray
public static int findMaximumSum(int[] a, int n)
{
// Stores previous smaller element
int []prev_smaller = findPrevious(a, n);
// Stores next smaller element
int []next_smaller = findNext(a, n);
int max_value = 0;
for (int i = 0; i < n; i++)
{
// Calculate contribution
// of each element
max_value = Math.Max(max_value,
a[i] * (next_smaller[i] -
prev_smaller[i] - 1));
}
// Return answer
return max_value;
}
// Function to generate previous smaller element
// for each array element
public static int[] findPrevious(int[] a, int n)
{
int []ps = new int[n];
// The first element has no
// previous smaller
ps[0] = -1;
// Stack to keep track of elements
// that have occurred previously
Stack stack = new Stack();
// Push the first index
stack.Push(0);
for (int i = 1; i < a.Length; i++)
{
// Pop all the elements until the previous
// element is smaller than current element
while (stack.Count > 0 &&
a[stack.Peek()] >= a[i])
stack.Pop();
// Store the previous smaller element
ps[i] = stack.Count > 0 ? stack.Peek() : -1;
// Push the index of the current element
stack.Push(i);
}
// Return the array
return ps;
}
// Function to generate next smaller element
// for each array element
public static int[] findNext(int[] a, int n)
{
int []ns = new int[n];
ns[n - 1] = n;
// Stack to keep track of elements
// that have occurring next
Stack stack = new Stack();
stack.Push(n - 1);
// Iterate in reverse order
// for calculating next smaller
for (int i = n - 2; i >= 0; i--)
{
// Pop all the elements until the
// next element is smaller
// than current element
while (stack.Count > 0 &&
a[stack.Peek()] >= a[i])
stack.Pop();
// Store the next smaller element
ns[i] = stack.Count > 0 ? stack.Peek()
: a.Length;
// Push the index of the current element
stack.Push(i);
}
// Return the array
return ns;
}
// Driver Code
public static void Main(String []args)
{
int n = 3;
int []a = { 80, 48, 82 };
Console.WriteLine(findMaximumSum(a, n));
}
}
// This code is contributed by Amit Katiyar
输出:
144
时间复杂度: O(N)
辅助空间: O(N)