📌  相关文章
📜  总和是数组大小倍数的最小子数组

📅  最后修改于: 2022-05-13 01:57:51.443000             🧑  作者: Mango

总和是数组大小倍数的最小子数组

给定一个大小为 N 的数组,我们需要找到其和可被数组大小 N 整除的最小大小的子数组。
例子 :

Input  : arr[] = [1, 1, 2, 2, 4, 2]    
Output : [2 4]
Size of array, N = 6    
Following subarrays have sum as multiple of N
[1, 1, 2, 2], [2, 4], [1, 1, 2, 2, 4, 2]
The smallest among all is [2 4]

考虑到以下事实,我们可以解决这个问题,

Let S[i] denotes sum of first i elements i.e.  
   S[i] = a[1] + a[2] .. + a[i]
Now subarray arr(i, i + x) has sum multiple of N then,
  (arr(i] + arr[i+1] + .... + arr[i + x])) % N = 0
  (S[i+x] – S[i] ) % N  = 0
  S[i] % N = S[i + x] % N 

我们需要找到满足上述条件的 x 的最小值。这可以使用另一个大小为 N 的数组 modIdx 在 O(N) 时间复杂度的单次迭代中实现。数组modIdx初始化为所有元素为 -1。 modIdx[k]将在每次迭代中用 i 更新,其中 k = sum % N。
现在在每次迭代中,我们需要根据 sum % N 的值更新modIdx[k]
我们需要检查两件事,
如果在任何时刻 k = 0 并且这是我们第一次更新modIdx[0] (即modIdx[0]为 -1)
然后我们将 x 分配给 i + 1,因为 (i + 1) 将是子数组的长度,其和是 N 的倍数
在其他情况下,只要我们得到一个 mod 值,如果这个索引不是 -1,这意味着它被其他一些总和值更新,其索引存储在那个索引处,我们用这个差值更新 x,即通过 i – modIdx [k]
在上述每个操作之后,我们更新子数组的最小长度和相应的起始索引和结束索引。最后,这为我们的问题提供了解决方案。

C++
// C++ program to find subarray whose sum
// is multiple of size
#include 
using namespace std;
 
// Method prints smallest subarray whose sum is
// multiple of size
void printSubarrayMultipleOfN(int arr[], int N)
{
    // A direct index table to see if sum % N
    // has appeared before or not.  
    int modIdx[N];
 
    //  initialize all mod index with -1
    for (int i = 0; i < N; i++)
        modIdx[i] = -1;
 
    // initializing minLen and curLen with larger
    // values
    int minLen = N + 1;
    int curLen = N + 1;
 
    // To store sum of array elements
    int sum = 0;
 
    //  looping for each value of array
    int l, r;
    for (int i = 0; i < N; i++)
    {
        sum += arr[i];
        sum %= N;
 
        // If this is the first time we have
        // got mod value as 0, then S(0, i) % N
        // == 0
        if (modIdx[sum] == -1 && sum == 0)
            curLen = i + 1;
 
        // If we have reached this mod before then
        // length of subarray will be i - previous_position
        if (modIdx[sum] != -1)
            curLen = i - modIdx[sum];
 
        //  choose minimum length os subarray till now
        if (curLen < minLen)
        {
            minLen = curLen;
 
            //  update left and right indices of subarray
            l = modIdx[sum] + 1;
            r = i;
        }
        modIdx[sum] = i;
    }
 
    //  print subarray
    for (int i = l; i <= r; i++)
        cout << arr[i] << " ";
    cout << endl;
}
 
//  Driver code to test above method
int main()
{
    int arr[] = {1, 1, 2, 2, 4, 2};
    int N = sizeof(arr) / sizeof(int);
 
    printSubarrayMultipleOfN(arr, N);
    return 0;
}


Java
// Java program to find subarray whose sum
// is multiple of size
class GFG {
     
    // Method prints smallest subarray whose sum is
    // multiple of size
    static void printSubarrayMultipleOfN(int arr[],
                                              int N)
    {
         
        // A direct index table to see if sum % N
        // has appeared before or not.
        int modIdx[] = new int[N];
 
        // initialize all mod index with -1
        for (int i = 0; i < N; i++)
            modIdx[i] = -1;
 
        // initializing minLen and curLen with
        // larger values
        int minLen = N + 1;
        int curLen = N + 1;
 
        // To store sum of array elements
        int sum = 0;
 
        // looping for each value of array
        int l = 0, r = 0;
         
        for (int i = 0; i < N; i++) {
            sum += arr[i];
            sum %= N;
 
            // If this is the first time we
            // have got mod value as 0, then
            // S(0, i) % N == 0
            if (modIdx[sum] == -1 && sum == 0)
                curLen = i + 1;
 
            // If we have reached this mod before
            // then length of subarray will be i
            // - previous_position
            if (modIdx[sum] != -1)
                curLen = i - modIdx[sum];
 
            // choose minimum length os subarray
            // till now
            if (curLen < minLen) {
                minLen = curLen;
 
                // update left and right indices
                // of subarray
                l = modIdx[sum] + 1;
                r = i;
            }
             
            modIdx[sum] = i;
        }
 
        // print subarray
        for (int i = l; i <= r; i++)
            System.out.print(arr[i] + " ");
             
        System.out.println();
    }
     
    // Driver program
    public static void main(String arg[])
    {
        int arr[] = { 1, 1, 2, 2, 4, 2 };
        int N = arr.length;
 
        printSubarrayMultipleOfN(arr, N);
    }
}
 
// This code is contributed by Anant Agarwal.


Python3
# Python3 program to find subarray
# whose sum is multiple of size
 
# Method prints smallest subarray
# whose sum is multiple of size
def printSubarrayMultipleOfN(arr, N):
 
    # A direct index table to see if sum % N
    # has appeared before or not.
    modIdx = [0 for i in range(N)]
 
    # initialize all mod index with -1
    for i in range(N):
        modIdx[i] = -1
 
    # initializing minLen and curLen
    # with larger values
    minLen = N + 1
    curLen = N + 1
 
    # To store sum of array elements
    sum = 0
 
    # looping for each value of array
    l = 0; r = 0
    for i in range(N):
     
        sum += arr[i]
        sum %= N
 
        # If this is the first time we have
        # got mod value as 0, then S(0, i) % N
        # == 0
        if (modIdx[sum] == -1 and sum == 0):
            curLen = i + 1
 
        # If we have reached this mod before then
        # length of subarray will be i - previous_position
        if (modIdx[sum] != -1):
            curLen = i - modIdx[sum]
 
        # choose minimum length os subarray till now
        if (curLen < minLen):
         
            minLen = curLen
 
            # update left and right indices of subarray
            l = modIdx[sum] + 1
            r = i
         
        modIdx[sum] = i
     
    # print subarray
    for i in range(l, r + 1):
        print(arr[i] , " ", end = "")
    print()
 
# Driver program
arr = [1, 1, 2, 2, 4, 2]
N = len(arr)
printSubarrayMultipleOfN(arr, N)
 
# This code is contributed by Anant Agarwal.


C#
// C# program to find subarray whose sum
// is multiple of size
using System;
class GFG {
     
    // Method prints smallest subarray whose sum is
    // multiple of size
    static void printSubarrayMultipleOfN(int []arr,
                                            int N)
    {
         
        // A direct index table to see if sum % N
        // has appeared before or not.
        int []modIdx = new int[N];
 
        // initialize all mod index with -1
        for (int i = 0; i < N; i++)
            modIdx[i] = -1;
 
        // initializing minLen and curLen with
        // larger values
        int minLen = N + 1;
        int curLen = N + 1;
 
        // To store sum of array elements
        int sum = 0;
 
        // looping for each value of array
        int l = 0, r = 0;
         
        for (int i = 0; i < N; i++) {
            sum += arr[i];
            sum %= N;
 
            // If this is the first time we
            // have got mod value as 0, then
            // S(0, i) % N == 0
            if (modIdx[sum] == -1 && sum == 0)
                curLen = i + 1;
 
            // If we have reached this mod before
            // then length of subarray will be i
            // - previous_position
            if (modIdx[sum] != -1)
                curLen = i - modIdx[sum];
 
            // choose minimum length os subarray
            // till now
            if (curLen < minLen) {
                minLen = curLen;
 
                // update left and right indices
                // of subarray
                l = modIdx[sum] + 1;
                r = i;
            }
             
            modIdx[sum] = i;
        }
 
        // print subarray
        for (int i = l; i <= r; i++)
            Console.Write(arr[i] + " ");
             
        Console.WriteLine();
    }
     
    // Driver Code
    public static void Main()
    {
        int []arr = {1, 1, 2, 2, 4, 2};
        int N = arr.Length;
 
        printSubarrayMultipleOfN(arr, N);
    }
}
 
// This code is contributed by nitin mittal.


PHP


Javascript


输出:

2 4