📌  相关文章
📜  查找一个总和可被数组大小整除的子数组

📅  最后修改于: 2021-05-04 22:52:35             🧑  作者: Mango

给定长度为N的数组arr [] 。任务是检查是否存在任何子数组,其总和是N的倍数。如果存在这样的子数组,则打印该子数组的开始和结束索引,否则打印-1 。如果有多个此类子数组,请打印其中的任何一个。

例子:

天真的方法:天真的方法是生成所有子数组并计算它们的总和。如果任何子数组的总和是N的倍数,则返回起始索引和终止索引。

时间复杂度: O(N 3 )

更好的方法:更好的方法是维护一个前缀和数组,该数组存储所有先前元素的和。要计算索引i和j之间的子数组的总和,我们可以使用以下公式:

现在检查每个子数组的总和是否为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。
对于数字序列,如下所示:

在上面的序列中,有N个术语,可能有两种情况:

  1. 如果以上前缀和之一是N的倍数,则打印第i个子数组索引。
  2. 如果以上序列元素都不位于N0模类中,则剩下(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)