给定一个由n个元素组成的数组和一个整数m。任务是找到其子阵列模m的总和的最大值,即找到每个子阵列mod m的总和并打印此模运算的最大值。
例子:
Input : arr[] = { 3, 3, 9, 9, 5 }
m = 7
Output : 6
All sub-arrays and their value:
{ 9 } => 9%7 = 2
{ 3 } => 3%7 = 3
{ 5 } => 5%7 = 5
{ 9, 5 } => 14%7 = 2
{ 9, 9 } => 18%7 = 4
{ 3, 9 } => 12%7 = 5
{ 3, 3 } => 6%7 = 6
{ 3, 9, 9 } => 21%7 = 0
{ 3, 3, 9 } => 15%7 = 1
{ 9, 9, 5 } => 23%7 = 2
{ 3, 3, 9, 9 } => 24%7 = 3
{ 3, 9, 9, 5 } => 26%7 = 5
{ 3, 3, 9, 9, 5 } => 29%7 = 1
Input : arr[] = {10, 7, 18}
m = 13
Output : 12
The subarray {7, 18} has maximum sub-array
sum modulo 13.
方法1(蛮力):
使用蛮力查找给定数组的所有子数组,并找到每个子数组mod m的总和,并跟踪最大值。
方法2(有效方法):
这个想法是计算数组的前缀和。我们找到以每个索引结尾的最大和,最后返回总的最大。要找到以index处的索引结尾的最大和,我们需要找到以i结尾的最大和的起点。以下步骤说明了如何找到起点。
Let prefix sum for index i be prefixi, i.e.,
prefixi = (arr[0] + arr[1] + .... arr[i] ) % m
Let maximum sum ending with i be, maxSumi.
Let this sum begins with index j.
maxSumi = (prefixi - prefixj + m) % m
From above expression it is clear that the
value of maxSumi becomes maximum when
prefixj is greater than prefixi
and closest to prefixi
以上算法主要有两个操作。
- 存储所有前缀。
- 对于当前前缀,前缀i ,找到大于或等于前缀i + 1的最小值。
对于上述操作,最适合使用自平衡二进制搜索树,例如AVL树,红黑树等。在下面的实现中,我们使用STL中的set实现自平衡二进制搜索树。
以下是此方法的实现:
C++
// C++ program to find sub-array having maximum
// sum of elements modulo m.
#include
using namespace std;
// Return the maximum sum subarray mod m.
int maxSubarray(int arr[], int n, int m)
{
int x, prefix = 0, maxim = 0;
set S;
S.insert(0);
// Traversing the array.
for (int i = 0; i < n; i++)
{
// Finding prefix sum.
prefix = (prefix + arr[i])%m;
// Finding maximum of prefix sum.
maxim = max(maxim, prefix);
// Finding iterator pointing to the first
// element that is not less than value
// "prefix + 1", i.e., greater than or
// equal to this value.
auto it = S.lower_bound(prefix+1);
if (it != S.end())
maxim = max(maxim, prefix - (*it) + m );
// Inserting prefix in the set.
S.insert(prefix);
}
return maxim;
}
// Driver Program
int main()
{
int arr[] = { 3, 3, 9, 9, 5 };
int n = sizeof(arr)/sizeof(arr[0]);
int m = 7;
cout << maxSubarray(arr, n, m) << endl;
return 0;
}
Java
// Java program to find sub-array
// having maximum sum of elements modulo m.
import java.util.*;
class GFG
{
// Return the maximum sum subarray mod m.
static int maxSubarray(int[] arr, int n, int m)
{
int x = 0;
int prefix = 0;
int maxim = 0;
Set S = new HashSet();
S.add(0);
// Traversing the array.
for (int i = 0; i < n; i++)
{
// Finding prefix sum.
prefix = (prefix + arr[i]) % m;
// Finding maximum of prefix sum.
maxim = Math.max(maxim, prefix);
// Finding iterator poing to the first
// element that is not less than value
// "prefix + 1", i.e., greater than or
// equal to this value.
int it = 0;
for (int j : S)
{
if (j >= prefix + 1)
it = j;
}
if (it != 0)
{
maxim = Math.max(maxim, prefix - it + m);
}
// adding prefix in the set.
S.add(prefix);
}
return maxim;
}
// Driver code
public static void main(String[] args)
{
// Driver Code
int[] arr = new int[] { 3, 3, 9, 9, 5 };
int n = 5;
int m = 7;
System.out.print(maxSubarray(arr, n, m));
}
}
// This code is contributed by pratham76.
Python3
# Python3 program to find sub-array
# having maximum sum of elements modulo m.
# Return the maximum sum subarray mod m.
def maxSubarray(arr, n, m):
x = 0
prefix = 0
maxim = 0
S = set()
S.add(0)
# Traversing the array.
for i in range(n):
# Finding prefix sum.
prefix = (prefix + arr[i]) % m
# Finding maximum of prefix sum.
maxim = max(maxim, prefix)
# Finding iterator poing to the first
# element that is not less than value
# "prefix + 1", i.e., greater than or
# equal to this value.
it = 0
for i in S:
if i >= prefix + 1:
it = i
if (it != 0) :
maxim = max(maxim, prefix - it + m )
# adding prefix in the set.
S.add(prefix)
return maxim
# Driver Code
arr = [3, 3, 9, 9, 5]
n = 5
m = 7
print(maxSubarray(arr, n, m))
# This code is contributed by
# Shubham Singh(SHUBHAMSINGH10)
C#
// C# program to find sub-array
// having maximum sum of elements modulo m.
using System;
using System.Collections;
using System.Collections.Generic;
class GFG
{
// Return the maximum sum subarray mod m.
static int maxSubarray(int[] arr, int n, int m)
{
int prefix = 0;
int maxim = 0;
HashSet S = new HashSet();
S.Add(0);
// Traversing the array.
for (int i = 0; i < n; i++)
{
// Finding prefix sum.
prefix = (prefix + arr[i]) % m;
// Finding maximum of prefix sum.
maxim = Math.Max(maxim, prefix);
// Finding iterator poing to the first
// element that is not less than value
// "prefix + 1", i.e., greater than or
// equal to this value.
int it = 0;
foreach(int j in S)
{
if (j >= prefix + 1)
it = j;
}
if (it != 0)
{
maxim = Math.Max(maxim, prefix - it + m);
}
// adding prefix in the set.
S.Add(prefix);
}
return maxim;
}
// Driver code
public static void Main(string[] args)
{
int[] arr = new int[] { 3, 3, 9, 9, 5 };
int n = 5;
int m = 7;
Console.Write(maxSubarray(arr, n, m));
}
}
// This code is contributed by rutvik_56.
输出:
6