Prefix Sum and Sliding Window 04
Given an array containing N integers and a positive integer K, find the length of the longest sub array with sum of the elements divisible by the given values k.
Problem link :- click here
Code
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
//LONGEST SUBARRAY WITH SUM DIVISIBLE BY K
public class Prefix_sum__Sliding_window_04
{
static int longestSubarrayWithSumDivisibleByK(int arr[], int k)
{
/*
*) This problem is similar to problem 2 where we have used the psa(prefix sum array).
*) Here instead of `psa` we are creating `modarr`
such that modarr[i] = psa[i] % k
*) If any element in `modarr` is == 0, then there is a sub-array starting from index 0
having sum of elements divisible by k.
*) How to verify sub-arrays which doesn't start with index 0?
*) Consider a example: arr = {2, 7, 6, 1, 4, 5} k = 3
psa = {2, 9, 15, 16, 20, 25}
modarr = {2, 0, 0, 1, 2, 1}
If there is a sub-array with sum divisible by k, then modarr will have some elements repeated.
i.e.., 8%3 = 2 and 26 % 3 = 2
(18 + 8) % 3 = 2
If we remove 8 then we will get a sub-array of sum = 18 which is divisible by 3.
*) We will store the first occurrence of a modulus in a hashMap with its index,
So that we can find the length of the sub-array.
*/
// Creating modarr
int modarr[] = new int[arr.length];
int sum = 0;
for(int i=0; i<arr.length; i++)
{
sum += arr[i];
modarr[i] = ((sum % k) + k) % k;
}
int max = 0;
Map<Integer, Integer> hp = new HashMap<>();
for(int i=0; i<arr.length; i++)
{
// Here we don't check if max < i + 1. Because as we go in the array `i` only increases
// and we start with max = 0.
if(modarr[i] == 0)
max = i + 1; // i + 1 ----> Number of elements in the sub-array whose sum is divisible by k
// Repeating modulus
if( hp.containsKey(modarr[i]) )
{
if(max < ( i - hp.get(modarr[i]) ) )
max = i - hp.get(modarr[i]);
}
else
hp.put(modarr[i], i); // Adding the new modulus to the hashMap
}
return max;
}
static int longestSubarrayWithSumDivisibleByK2(int[] arr, int k)
{
/*
In this function instead of storing the modulus values in an array we will use it on the go.
*/
Map<Integer, Integer> hp = new HashMap<>();
int max = 0;
int sum = 0;
for(int i=0; i<arr.length; i++)
{
sum += arr[i];
int mod = ((sum % k) + k) % k;
if(mod == 0)
max = i + 1;
if( hp.containsKey(mod) )
{
if(max < (i - hp.get(mod)) )
max = i - hp.get(mod);
}
else
hp.put(mod, i);
}
return max;
}
public static void main(String[] args)
{
Scanner s = new Scanner(System.in);
// Taking size of array and array as input from the user
System.out.print("Enter the size of the array : ");
int n = s.nextInt();
int[] arr = new int[n];
System.out.println("Enter the array elements : ");
for(int i=0; i<n; i++)
arr[i] = s.nextInt();
System.out.print("Enter the the value of k : ");
int k = s.nextInt();
System.out.println(longestSubarrayWithSumDivisibleByK2(arr, k));
}
}
Comments
Post a Comment