给定长度为N的数组arr [] 。任务是检查是否存在任何子数组,其总和是N的倍数。如果存在这样的子数组,则打印该子数组的开始和结束索引,否则打印-1 。如果有多个此类子数组,请打印其中的任何一个。
例子:
Input: arr[] = {7, 5, 3, 7}
Output: 0 1
Sub-array from index 0 to 1 is [7, 5]
sum of this subarray is 12 which is a multiple of 4
Input: arr[] = {3, 7, 14}
Output: 0 0
天真的方法:天真的方法是生成所有子数组并计算它们的总和。如果任何子数组的总和是N的倍数,则返回起始索引和终止索引。
时间复杂度: O(N 3 )
更好的方法:更好的方法是维护一个前缀和数组,该数组存储所有先前元素的和。要计算索引i和j之间的子数组的总和,我们可以使用以下公式:
subarray sum[i:j] = presum[j]-presum[i-1]
现在检查每个子数组的总和是否为N的倍数。
下面是上述方法的实现:
C++
// C++ implementation of above approach
#include
using namespace std;
// Function to find a subarray
// whose sum is a multiple of N
void CheckSubarray(int arr[], int N)
{
// Prefix sum array to store cumulative sum
int presum[N + 1] = { 0 };
// Single state dynamic programming
// relation for prefix sum array
for (int i = 1; i <= N; i += 1) {
presum[i] = presum[i - 1] + arr[i - 1];
}
// Generating all sub-arrays
for (int i = 1; i <= N; i += 1) {
for (int j = i; j <= N; j += 1) {
// If the sum of the sub-array[i:j]
// is a multiple of N
if ((presum[j] - presum[i - 1]) % N == 0) {
cout << i - 1 << " " << j - 1;
return;
}
}
}
// If the function reaches here it means
// there are no subarrays with sum
// as a multiple of N
cout << -1;
}
// Driver code
int main()
{
int arr[] = { 7, 5, 3, 7 };
int N = sizeof(arr) / sizeof(arr[0]);
CheckSubarray(arr, N);
return 0;
}
Java
// Java implementation of above approach
import java.io.*;
class GFG
{
// Function to find a subarray
// whose sum is a multiple of N
static void CheckSubarray(int arr[], int N)
{
// Prefix sum array to store cumulative sum
int presum[] = new int[N + 1];
// Single state dynamic programming
// relation for prefix sum array
for (int i = 1; i <= N; i += 1)
{
presum[i] = presum[i - 1] + arr[i - 1];
}
// Generating all sub-arrays
for (int i = 1; i <= N; i += 1)
{
for (int j = i; j <= N; j += 1)
{
// If the sum of the sub-array[i:j]
// is a multiple of N
if ((presum[j] - presum[i - 1]) % N == 0)
{
System.out.print((i - 1) + " " + (j - 1));
return;
}
}
}
// If the function reaches here it means
// there are no subarrays with sum
// as a multiple of N
System.out.print(-1);
}
// Driver code
public static void main (String[] args)
{
int []arr = { 7, 5, 3, 7 };
int N = arr.length;
CheckSubarray(arr, N);
}
}
// This code is contributed by anuj_67..
Python3
# Python3 implementation of above approach
# Function to find a subarray
# whose sum is a multiple of N
def CheckSubarray(arr, N):
# Prefix sum array to store cumulative sum
presum=[0 for i in range(N + 1)]
# Single state dynamic programming
# relation for prefix sum array
for i in range(1, N+1):
presum[i] = presum[i - 1] + arr[i - 1]
# Generating all sub-arrays
for i in range(1, N+1):
for j in range(i, N+1):
# If the sum of the sub-array[i:j]
# is a multiple of N
if ((presum[j] - presum[i - 1]) % N == 0):
print(i - 1,j - 1)
return
# If the function reaches here it means
# there are no subarrays with sum
# as a multiple of N
print("-1")
# Driver code
arr = [ 7, 5, 3, 7]
N = len(arr)
CheckSubarray(arr, N)
# This code is contributed by mohit kumar 29
C#
// C# implementation of above approach
using System;
class GFG
{
// Function to find a subarray
// whose sum is a multiple of N
static void CheckSubarray(int []arr, int N)
{
// Prefix sum array to store cumulative sum
int []presum = new int[N + 1];
// Single state dynamic programming
// relation for prefix sum array
for (int i = 1; i <= N; i += 1)
{
presum[i] = presum[i - 1] + arr[i - 1];
}
// Generating all sub-arrays
for (int i = 1; i <= N; i += 1)
{
for (int j = i; j <= N; j += 1)
{
// If the sum of the sub-array[i:j]
// is a multiple of N
if ((presum[j] - presum[i - 1]) % N == 0)
{
Console.Write((i - 1) + " " + (j - 1));
return;
}
}
}
// If the function reaches here it means
// there are no subarrays with sum
// as a multiple of N
Console.Write(-1);
}
// Driver code
public static void Main ()
{
int []arr = { 7, 5, 3, 7 };
int N = arr.Length;
CheckSubarray(arr, N);
}
}
// This code is contributed by anuj_67..
C++
// C++ implementation of above approach
#include
using namespace std;
// Function to check is there exists a
// subarray whose sum is a multiple of N
void CheckSubarray(int arr[], int N)
{
// Prefix sum array to store cumulative sum
int presum[N + 1] = { 0 };
// Single state dynamic programming
// relation for prefix sum array
for (int i = 1; i <= N; i += 1) {
presum[i] = presum[i - 1] + arr[i - 1];
}
// Modulo class vector
vector moduloclass[N];
// Storing the index value in the modulo class vector
for (int i = 1; i <= N; i += 1) {
moduloclass[presum[i] % N].push_back(i - 1);
}
// If there exists a sub-array with
// startig index equal to zero
if (moduloclass[0].size() > 0) {
cout << 0 << " " << moduloclass[0][0];
return;
}
for (int i = 1; i < N; i += 1) {
// In this class, there are more than two presums%N
// Hence difference of any two subarrays would be a
// multiple of N
if (moduloclass[i].size() >= 2) {
// 0 based indexing
cout << moduloclass[i][0] + 1 << " " << moduloclass[i][1];
return;
}
}
}
// Driver code
int main()
{
int arr[] = { 7, 3, 5, 2 };
int N = sizeof(arr) / sizeof(arr[0]);
CheckSubarray(arr, N);
return 0;
}
Java
// Java implementation of above approach
import java.util.*;
class GFG
{
// Function to check is there exists a
// subarray whose sum is a multiple of N
static void CheckSubarray(int arr[], int N)
{
// Prefix sum array to store cumulative sum
int[] presum = new int[N + 1];
// Single state dynamic programming
// relation for prefix sum array
for (int i = 1; i <= N; i += 1)
{
presum[i] = presum[i - 1] + arr[i - 1];
}
// Modulo class vector
Vector[] moduloclass = new Vector[N];
for (int i = 0; i < N; i += 1)
{
moduloclass[i] = new Vector<>();
}
// Storing the index value
// in the modulo class vector
for (int i = 1; i <= N; i += 1)
{
moduloclass[presum[i] % N].add(i - 1);
}
// If there exists a sub-array with
// startig index equal to zero
if (moduloclass[0].size() > 0)
{
System.out.print(0 + " " +
moduloclass[0].get(0));
return;
}
for (int i = 1; i < N; i += 1)
{
// In this class, there are more than
// two presums%N. Hence difference of
// any two subarrays would be a multiple of N
if (moduloclass[i].size() >= 2)
{
// 0 based indexing
System.out.print(moduloclass[i].get(0) + 1 +
" " + moduloclass[i].get(1));
return;
}
}
}
// Driver code
public static void main(String args[])
{
int arr[] = {7, 3, 5, 2};
int N = arr.length;
CheckSubarray(arr, N);
}
}
// This code is contributed by 29AjayKumar
Python3
# Python 3 implementation of above approach
# Function to check is there exists a
# subarray whose sum is a multiple of N
def CheckSubarray(arr, N):
# Prefix sum array to store cumulative sum
presum = [0 for i in range(N+1)]
# Single state dynamic programming
# relation for prefix sum array
for i in range(1,N+1):
presum[i] = presum[i - 1] + arr[i - 1]
# Modulo class vector
moduloclass = [[]]*N
# Storing the index value in the modulo class vector
for i in range(1,N+1,1):
moduloclass[presum[i] % N].append(i - 1)
# If there exists a sub-array with
# startig index equal to zero
if (len(moduloclass[0]) > 0):
print(0+1,moduloclass[0][0]+2)
return
for i in range(1,N):
# In this class, there are more than two presums%N
# Hence difference of any two subarrays would be a
# multiple of N
if (len(moduloclass[i]) >= 2):
# 0 based indexing
print(moduloclass[i][0] + 1,moduloclass[i][1])
return
# Driver code
if __name__ == '__main__':
arr = [7, 3, 5, 2]
N = len(arr)
CheckSubarray(arr, N)
# This code is contributed by
# Surendra_Gangwar
C#
// C# implementation of the approach
using System;
using System.Collections.Generic;
class GFG
{
// Function to check is there exists a
// subarray whose sum is a multiple of N
static void CheckSubarray(int []arr, int N)
{
// Prefix sum array to store cumulative sum
int[] presum = new int[N + 1];
// Single state dynamic programming
// relation for prefix sum array
for (int i = 1; i <= N; i += 1)
{
presum[i] = presum[i - 1] + arr[i - 1];
}
// Modulo class vector
List[] moduloclass = new List[N];
for (int i = 0; i < N; i += 1)
{
moduloclass[i] = new List();
}
// Storing the index value
// in the modulo class vector
for (int i = 1; i <= N; i += 1)
{
moduloclass[presum[i] % N].Add(i - 1);
}
// If there exists a sub-array with
// startig index equal to zero
if (moduloclass[0].Count > 0)
{
Console.Write(0 + " " +
moduloclass[0][0]);
return;
}
for (int i = 1; i < N; i += 1)
{
// In this class, there are more than
// two presums%N. Hence difference of
// any two subarrays would be a multiple of N
if (moduloclass[i].Count >= 2)
{
// 0 based indexing
Console.Write(moduloclass[i][0] + 1 +
" " + moduloclass[i][1]);
return;
}
}
}
// Driver code
public static void Main(String []args)
{
int []arr = {7, 3, 5, 2};
int N = arr.Length;
CheckSubarray(arr, N);
}
}
// This code is contributed by Rajput-Ji
0 1
时间复杂度: O(N 2 )
高效的方法:这个想法是使用鸽子-孔原理。让我们假设该阵列元素是A 1,A 2 … A N。
对于数字序列,如下所示:
a1, a1 + a2, a1 + a2 + a3, …, a1 + a2 +a3 + … +aN
在上面的序列中,有N个术语,可能有两种情况:
- 如果以上前缀和之一是N的倍数,则打印第i个子数组索引。
- 如果以上序列元素都不位于N的0模类中,则剩下(N – 1)个模类。根据信鸽原理,有N个信鸽(前缀和序列的元素)和(N – 1)个信鸽(模类),我们可以说至少有两个元素属于同一个模子类。这两个元素之间的差将给出一个子数组,其总和将为N的倍数。
可以看出,总是有可能获得这种子阵列。
下面是上述方法的实现:
C++
// C++ implementation of above approach
#include
using namespace std;
// Function to check is there exists a
// subarray whose sum is a multiple of N
void CheckSubarray(int arr[], int N)
{
// Prefix sum array to store cumulative sum
int presum[N + 1] = { 0 };
// Single state dynamic programming
// relation for prefix sum array
for (int i = 1; i <= N; i += 1) {
presum[i] = presum[i - 1] + arr[i - 1];
}
// Modulo class vector
vector moduloclass[N];
// Storing the index value in the modulo class vector
for (int i = 1; i <= N; i += 1) {
moduloclass[presum[i] % N].push_back(i - 1);
}
// If there exists a sub-array with
// startig index equal to zero
if (moduloclass[0].size() > 0) {
cout << 0 << " " << moduloclass[0][0];
return;
}
for (int i = 1; i < N; i += 1) {
// In this class, there are more than two presums%N
// Hence difference of any two subarrays would be a
// multiple of N
if (moduloclass[i].size() >= 2) {
// 0 based indexing
cout << moduloclass[i][0] + 1 << " " << moduloclass[i][1];
return;
}
}
}
// Driver code
int main()
{
int arr[] = { 7, 3, 5, 2 };
int N = sizeof(arr) / sizeof(arr[0]);
CheckSubarray(arr, N);
return 0;
}
Java
// Java implementation of above approach
import java.util.*;
class GFG
{
// Function to check is there exists a
// subarray whose sum is a multiple of N
static void CheckSubarray(int arr[], int N)
{
// Prefix sum array to store cumulative sum
int[] presum = new int[N + 1];
// Single state dynamic programming
// relation for prefix sum array
for (int i = 1; i <= N; i += 1)
{
presum[i] = presum[i - 1] + arr[i - 1];
}
// Modulo class vector
Vector[] moduloclass = new Vector[N];
for (int i = 0; i < N; i += 1)
{
moduloclass[i] = new Vector<>();
}
// Storing the index value
// in the modulo class vector
for (int i = 1; i <= N; i += 1)
{
moduloclass[presum[i] % N].add(i - 1);
}
// If there exists a sub-array with
// startig index equal to zero
if (moduloclass[0].size() > 0)
{
System.out.print(0 + " " +
moduloclass[0].get(0));
return;
}
for (int i = 1; i < N; i += 1)
{
// In this class, there are more than
// two presums%N. Hence difference of
// any two subarrays would be a multiple of N
if (moduloclass[i].size() >= 2)
{
// 0 based indexing
System.out.print(moduloclass[i].get(0) + 1 +
" " + moduloclass[i].get(1));
return;
}
}
}
// Driver code
public static void main(String args[])
{
int arr[] = {7, 3, 5, 2};
int N = arr.length;
CheckSubarray(arr, N);
}
}
// This code is contributed by 29AjayKumar
Python3
# Python 3 implementation of above approach
# Function to check is there exists a
# subarray whose sum is a multiple of N
def CheckSubarray(arr, N):
# Prefix sum array to store cumulative sum
presum = [0 for i in range(N+1)]
# Single state dynamic programming
# relation for prefix sum array
for i in range(1,N+1):
presum[i] = presum[i - 1] + arr[i - 1]
# Modulo class vector
moduloclass = [[]]*N
# Storing the index value in the modulo class vector
for i in range(1,N+1,1):
moduloclass[presum[i] % N].append(i - 1)
# If there exists a sub-array with
# startig index equal to zero
if (len(moduloclass[0]) > 0):
print(0+1,moduloclass[0][0]+2)
return
for i in range(1,N):
# In this class, there are more than two presums%N
# Hence difference of any two subarrays would be a
# multiple of N
if (len(moduloclass[i]) >= 2):
# 0 based indexing
print(moduloclass[i][0] + 1,moduloclass[i][1])
return
# Driver code
if __name__ == '__main__':
arr = [7, 3, 5, 2]
N = len(arr)
CheckSubarray(arr, N)
# This code is contributed by
# Surendra_Gangwar
C#
// C# implementation of the approach
using System;
using System.Collections.Generic;
class GFG
{
// Function to check is there exists a
// subarray whose sum is a multiple of N
static void CheckSubarray(int []arr, int N)
{
// Prefix sum array to store cumulative sum
int[] presum = new int[N + 1];
// Single state dynamic programming
// relation for prefix sum array
for (int i = 1; i <= N; i += 1)
{
presum[i] = presum[i - 1] + arr[i - 1];
}
// Modulo class vector
List[] moduloclass = new List[N];
for (int i = 0; i < N; i += 1)
{
moduloclass[i] = new List();
}
// Storing the index value
// in the modulo class vector
for (int i = 1; i <= N; i += 1)
{
moduloclass[presum[i] % N].Add(i - 1);
}
// If there exists a sub-array with
// startig index equal to zero
if (moduloclass[0].Count > 0)
{
Console.Write(0 + " " +
moduloclass[0][0]);
return;
}
for (int i = 1; i < N; i += 1)
{
// In this class, there are more than
// two presums%N. Hence difference of
// any two subarrays would be a multiple of N
if (moduloclass[i].Count >= 2)
{
// 0 based indexing
Console.Write(moduloclass[i][0] + 1 +
" " + moduloclass[i][1]);
return;
}
}
}
// Driver code
public static void Main(String []args)
{
int []arr = {7, 3, 5, 2};
int N = arr.Length;
CheckSubarray(arr, N);
}
}
// This code is contributed by Rajput-Ji
1 2
时间复杂度: O(N)