📌  相关文章
📜  要删除的最小子数组的长度以使剩余元素的总和可被 K 整除

📅  最后修改于: 2021-09-06 06:20:27             🧑  作者: Mango

给定一个整数数组arr[]和一个整数K ,任务是找到需要删除的最小子数组的长度,使得剩余数组元素的总和可以被K整除。不允许移除整个阵列。如果不可能,则打印“-1”

例子:

朴素的方法:最简单的方法是从给定的数组arr[]生成所有可能的子数组,不包括长度为N的子数组。现在,找到子数组的最小长度,使得数组所有元素的总和与该子数组中元素的总和之间的差能被K整除。如果不存在这样的子数组,则打印“-1”

时间复杂度: O(N 2 )
辅助空间: O(1)

高效的方法:为了优化上述方法,该想法基于以下观察:

请按照以下步骤解决此问题:

  • 将变量res初始化为 INT_MAX 来存储要移除的子数组的最小长度。
  • 计算total_sum和除以K 后的余数。
  • 创建一个辅助数组modArr[]来存储每个arr[i]K除时的余数:
  • 遍历给定的数组并维护一个 unordered_map 以存储遇到的余数的最近位置,并跟踪具有与target_remainder相同的余数的最小所需子数组。
  • 如果映射中存在任何等于(curr_remainder – target_remainder + K) % K 的键,则将该子数组长度存储在变量 res 中,作为找到的res和当前长度的最小值。
  • 以上后,如果res没有改变,则打印“-1”,否则打印res的值。

下面是上述方法的实现:

C++
// C++ program for the above approach
 
#include 
using namespace std;
 
// Function to find the length of the
// smallest subarray to be removed such
// that sum of elements is divisible by K
void removeSmallestSubarray(int arr[],
                            int n, int k)
{
    // Stores the remainder of each
    // arr[i] when divided by K
    int mod_arr[n];
 
    // Stores total sum of elements
    int total_sum = 0;
 
    // K has been added to each arr[i]
    // to handle -ve integers
    for (int i = 0; i < n; i++) {
        mod_arr[i] = (arr[i] + k) % k;
 
        // Update the total sum
        total_sum += arr[i];
    }
 
    // Remainder when total_sum
    // is divided by K
    int target_remainder
        = total_sum % k;
 
    // If given array is already
    // divisible by K
    if (target_remainder == 0) {
        cout << "0";
        return;
    }
 
    // Stores curr_remainder and the
    // most recent index at which
    // curr_remainder has occured
    unordered_map map1;
    map1[0] = -1;
 
    int curr_remainder = 0;
 
    // Stores required answer
    int res = INT_MAX;
 
    for (int i = 0; i < n; i++) {
 
        // Add current element to
        // curr_sum and take mod
        curr_remainder = (curr_remainder
                          + arr[i] + k)
                         % k;
 
        // Update current remainder index
        map1[curr_remainder] = i;
 
        int mod
            = (curr_remainder
               - target_remainder
               + k)
              % k;
 
        // If mod already exists in map
        // the subarray exists
        if (map1.find(mod) != map1.end())
            res = min(res, i - map1[mod]);
    }
 
    // If not possible
    if (res == INT_MAX || res == n) {
        res = -1;
    }
 
    // Print the result
    cout << res;
}
 
// Driver Code
int main()
{
    // Given array arr[]
    int arr[] = { 3, 1, 4, 2 };
 
    // Size of array
    int N = sizeof(arr) / sizeof(arr[0]);
 
    // Given K
    int K = 6;
 
    // Function Call
    removeSmallestSubarray(arr, N, K);
 
    return 0;
}


Java
// Java program for the
// above approach
import java.util.*;
class GFG{
 
// Function to find the length of the
// smallest subarray to be removed such
// that sum of elements is divisible by K
static void removeSmallestSubarray(int arr[],
                                   int n, int k)
{
  // Stores the remainder of each
  // arr[i] when divided by K
  int []mod_arr = new int[n];
 
  // Stores total sum of
  // elements
  int total_sum = 0;
 
  // K has been added to each
  // arr[i] to handle -ve integers
  for (int i = 0; i < n; i++)
  {
    mod_arr[i] = (arr[i] +
                  k) % k;
 
    // Update the total sum
    total_sum += arr[i];
  }
 
  // Remainder when total_sum
  // is divided by K
  int target_remainder =
      total_sum % k;
 
  // If given array is already
  // divisible by K
  if (target_remainder == 0)
  {
    System.out.print("0");
    return;
  }
 
  // Stores curr_remainder and the
  // most recent index at which
  // curr_remainder has occured
  HashMap map1 =
          new HashMap<>();
  map1.put(0, -1);
 
  int curr_remainder = 0;
 
  // Stores required answer
  int res = Integer.MAX_VALUE;
 
  for (int i = 0; i < n; i++)
  {
    // Add current element to
    // curr_sum and take mod
    curr_remainder = (curr_remainder +
                      arr[i] + k) % k;
 
    // Update current remainder
    // index
    map1.put(curr_remainder, i);
 
    int mod = (curr_remainder -
               target_remainder +
               k) % k;
 
    // If mod already exists in
    // map the subarray exists
    if (map1.containsKey(mod))
      res = Math.min(res, i -
                     map1.get(mod));
  }
 
  // If not possible
  if (res == Integer.MAX_VALUE ||
      res == n)
  {
    res = -1;
  }
 
  // Print the result
  System.out.print(res);
}
 
// Driver Code
public static void main(String[] args)
{
  // Given array arr[]
  int arr[] = {3, 1, 4, 2};
 
  // Size of array
  int N = arr.length;
 
  // Given K
  int K = 6;
 
  // Function Call
  removeSmallestSubarray(arr, N, K);
}
}
 
// This code is contributed by gauravrajput1


Python3
# Python3 program for the above approach
import sys
 
# Function to find the length of the
# smallest subarray to be removed such
# that sum of elements is divisible by K
def removeSmallestSubarray(arr, n, k):
     
    # Stores the remainder of each
    # arr[i] when divided by K
    mod_arr = [0] * n
  
    # Stores total sum of elements
    total_sum = 0
  
    # K has been added to each arr[i]
    # to handle -ve integers
    for i in range(n) :
        mod_arr[i] = (arr[i] + k) % k
  
        # Update the total sum
        total_sum += arr[i]
         
    # Remainder when total_sum
    # is divided by K
    target_remainder = total_sum % k
  
    # If given array is already
    # divisible by K
    if (target_remainder == 0):
        print("0")
        return
     
    # Stores curr_remainder and the
    # most recent index at which
    # curr_remainder has occured
    map1 = {}
    map1[0] = -1
  
    curr_remainder = 0
  
    # Stores required answer
    res = sys.maxsize
  
    for i in range(n):
         
        # Add current element to
        # curr_sum and take mod
        curr_remainder = (curr_remainder +
                             arr[i] + k) % k
  
        # Update current remainder index
        map1[curr_remainder] = i
  
        mod = (curr_remainder -
             target_remainder + k) % k
  
        # If mod already exists in map
        # the subarray exists
        if (mod in map1.keys()):
            res = min(res, i - map1[mod])
     
    # If not possible
    if (res == sys.maxsize or res == n):
        res = -1
     
    # Print the result
    print(res)
 
# Driver Code
 
# Given array arr[]
arr = [ 3, 1, 4, 2 ]
  
# Size of array
N = len(arr)
  
# Given K
K = 6
  
# Function Call
removeSmallestSubarray(arr, N, K)
 
# This code is contributed by susmitakundugoaldanga


C#
// C# program for the
// above approach
using System;
using System.Collections.Generic;
 
class GFG{
 
// Function to find the length of the
// smallest subarray to be removed such
// that sum of elements is divisible by K
static void removeSmallestSubarray(int []arr,
                                   int n, int k)
{
   
  // Stores the remainder of each
  // arr[i] when divided by K
  int []mod_arr = new int[n];
 
  // Stores total sum of
  // elements
  int total_sum = 0;
 
  // K has been added to each
  // arr[i] to handle -ve integers
  for(int i = 0; i < n; i++)
  {
    mod_arr[i] = (arr[i] + k) % k;
 
    // Update the total sum
    total_sum += arr[i];
  }
 
  // Remainder when total_sum
  // is divided by K
  int target_remainder = total_sum % k;
 
  // If given array is already
  // divisible by K
  if (target_remainder == 0)
  {
    Console.Write("0");
    return;
  }
 
  // Stores curr_remainder and the
  // most recent index at which
  // curr_remainder has occured
  Dictionary map1 = new Dictionary();
   
  map1.Add(0, -1);
 
  int curr_remainder = 0;
 
  // Stores required answer
  int res = int.MaxValue;
 
  for(int i = 0; i < n; i++)
  {
     
    // Add current element to
    // curr_sum and take mod
    curr_remainder = (curr_remainder +
                      arr[i] + k) % k;
 
    // Update current remainder
    // index
    map1[curr_remainder] = i;
 
    int mod = (curr_remainder -
               target_remainder +
               k) % k;
 
    // If mod already exists in
    // map the subarray exists
    if (map1.ContainsKey(mod))
      res = Math.Min(res, i -
                     map1[mod]);
  }
 
  // If not possible
  if (res == int.MaxValue ||
      res == n)
  {
    res = -1;
  }
   
  // Print the result
  Console.Write(res);
}
 
// Driver Code
public static void Main(String[] args)
{
   
  // Given array []arr
  int []arr = { 3, 1, 4, 2 };
 
  // Size of array
  int N = arr.Length;
 
  // Given K
  int K = 6;
 
  // Function Call
  removeSmallestSubarray(arr, N, K);
}
}
 
// This code is contributed by 29AjayKumar


输出:
1










时间复杂度: O(N)
辅助空间: O(N)

如果您想与行业专家一起参加直播课程,请参阅Geeks Classes Live