Check If Array Pair Sums Divisible by k
Given an array of integers and a number k, write a function that returns true if the given array can be divided into pairs such that the sum of every pair is divisible by k.
Examples:
Input: arr[] = [9, 7, 5, 3], k = 6
Output: True
We can divide the array into (9, 3) and (7, 5). Sum of both of these pairs is a multiple of 6.Input: arr[] = [92, 75, 65, 48, 45, 35], k = 10
Output: True
We can divide the array into (92, 48), (75, 65) and (45, 35). The sum of all these pairs are multiples of 10.Input: arr[] = [91, 74, 66, 48], k = 10
Output: False
Naive Approach - O(n^2) Time and O(n) Space
The idea is to iterate through every element arr[i]. Find if there is another not yet visited element that has a remainder like (k - arr[i]%k). If there is no such element, return false. If a pair is found, then mark both elements as visited.
#include <iostream>
#include <vector>
using namespace std;
bool canPairs(vector<int>& arr, int k) {
int n = arr.size();
if (n % 2 == 1)
return false;
int count = 0;
vector<int> vis(n, -1);
for (int i = 0; i < n; i++) {
for (int j = i + 1; j < n; j++) {
// If pair is divisible increment the
// count and mark elements as visited
if ((arr[i] + arr[j]) % k == 0 &&
vis[i] == -1 && vis[j] == -1) {
count++;
vis[i] = 1;
vis[j] = 1;
}
}
}
return (count == n / 2);
}
// Driver code
int main() {
vector<int> arr = {92, 75, 65, 48, 45, 35};
int k = 10;
cout << (canPairs(arr, k) ? "True" : "False");
return 0;
}
import java.util.*;
public class GfG {
public static boolean canPairs(int[] arr, int k) {
int n = arr.length;
if (n % 2 == 1)
return false;
int count = 0;
boolean[] vis = new boolean[n];
for (int i = 0; i < n; i++) {
for (int j = i + 1; j < n; j++) {
// If pair is divisible increment the
// count and mark elements as visited
if ((arr[i] + arr[j]) % k == 0 &&
!vis[i] && !vis[j]) {
count++;
vis[i] = true;
vis[j] = true;
}
}
}
return (count == n / 2);
}
public static void main(String[] args) {
int[] arr = {92, 75, 65, 48, 45, 35};
int k = 10;
System.out.println(canPairs(arr, k) ? "True" : "False");
}
}
def can_pairs(arr, k):
n = len(arr)
if n % 2 == 1:
return False
count = 0
vis = [-1] * n
for i in range(n):
for j in range(i + 1, n):
# If pair is divisible increment the
# count and mark elements as visited
if (arr[i] + arr[j]) % k == 0 and vis[i] == -1 and vis[j] == -1:
count += 1
vis[i] = 1
vis[j] = 1
return count == n // 2
# Driver code
arr = [92, 75, 65, 48, 45, 35]
k = 10
print("True" if can_pairs(arr, k) else "False")
// Include necessary namespaces
using System;
using System.Collections.Generic;
class Program {
static bool CanPairs(List<int> arr, int k) {
int n = arr.Count;
if (n % 2 == 1)
return false;
int count = 0;
bool[] vis = new bool[n];
for (int i = 0; i < n; i++) {
for (int j = i + 1; j < n; j++) {
// If pair is divisible increment
// the count and mark elements as visited
if ((arr[i] + arr[j]) % k == 0 &&
!vis[i] && !vis[j]) {
count++;
vis[i] = true;
vis[j] = true;
}
}
}
return (count == n / 2);
}
// Driver code
static void Main() {
List<int> arr = new List<int> { 92, 75, 65, 48, 45, 35 };
int k = 10;
Console.WriteLine(CanPairs(arr, k) ? "True" : "False");
}
}
// Function to check if pairs can be formed
function canPairs(arr, k) {
let n = arr.length;
if (n % 2 === 1)
return false;
let count = 0;
let vis = new Array(n).fill(-1);
for (let i = 0; i < n; i++) {
for (let j = i + 1; j < n; j++) {
// If pair is divisible increment the
// count and mark elements as visited
if ((arr[i] + arr[j]) % k === 0 &&
vis[i] === -1 && vis[j] === -1) {
count++;
vis[i] = 1;
vis[j] = 1;
}
}
}
return (count === n / 2);
}
// Driver code
let arr = [92, 75, 65, 48, 45, 35];
let k = 10;
console.log(canPairs(arr, k) ? "True" : "False");
Output
True
Expected Approach - Using Hash Map - O(n) Time and O(n) Space
1) If length of given array is odd, return false. An odd length array cannot be divided into pairs.
2) Traverse input array and count occurrences of all remainders (use (arr[i] % k) + k)%k for handling the case of negative integers as well).
freq[((arr[i] % k) + k) % k]++
3) Traverse input array again.
a) Find the remainder of the current element.
b) If remainder divides k into two halves, then there must be even occurrences of it as it forms pair with itself only.
c) If the remainder is 0, then there must be even occurrences.
d) Else, number of occurrences of current the remainder must be equal to a number of occurrences of "k - current remainder".
#include <bits/stdc++.h>
using namespace std;
// Returns true if arr can be divided into pairs
// with sum divisible by k.
bool canPairs(vector<int>& arr, int k)
{
int n = arr.size();
// An odd length array cannot be divided
// into pairs
if (n % 2 != 0)
return false;
// Create a frequency map to count occurrences
// of all remainders when divided by k.
unordered_map<int, int> freq;
// Count occurrences of all remainders
for (int x : arr)
freq[((x % k) + k) % k]++;
// Traverse the array and check pairs
for (int x : arr) {
int rem = ((x % k) + k) % k;
// If remainder divides k into two halves
if (2 * rem == k) {
if (freq[rem] % 2 != 0)
return false;
}
// If remainder is 0, there must be an even count
else if (rem == 0) {
if (freq[rem] % 2 != 0)
return false;
}
// Else occurrences of remainder and
// k - remainder must match
else if (freq[rem] != freq[k - rem])
return false;
}
return true;
}
// Driver code
int main()
{
vector<int> arr = {92, 75, 65, 48, 45, 35};
int k = 10;
canPairs(arr, k) ? cout << "True" : cout << "False";
return 0;
}
// JAVA program to check if arr[0..n-1] can be divided
// in pairs such that every pair is divisible by k.
import java.util.HashMap;
public class Divisiblepair {
// Returns true if arr[0..n-1] can be divided into pairs
// with sum divisible by k.
static boolean canPairs(int ar[], int k)
{
// An odd length array cannot be divided into pairs
if (ar.length % 2 == 1)
return false;
// Create a frequency array to count occurrences
// of all remainders when divided by k.
HashMap<Integer, Integer> hm = new HashMap<>();
// Count occurrences of all remainders
for (int i = 0; i < ar.length; i++) {
int rem = ((ar[i] % k) + k) % k;
if (!hm.containsKey(rem)) {
hm.put(rem, 0);
}
hm.put(rem, hm.get(rem) + 1);
}
// Traverse input array and use freq[] to decide
// if given array can be divided in pairs
for (int i = 0; i < ar.length; i++) {
// Remainder of current element
int rem = ((ar[i] % k) + k) % k;
// If remainder with current element divides
// k into two halves.
if (2 * rem == k) {
// Then there must be even occurrences of
// such remainder
if (hm.get(rem) % 2 == 1)
return false;
}
// If remainder is 0, then there must be two
// elements with 0 remainder
else if (rem == 0) {
// Then there must be even occurrences of
// such remainder
if (hm.get(rem) % 2 == 1)
return false;
}
// Else number of occurrences of remainder
// must be equal to number of occurrences of
// k - remainder
else {
if (hm.get(k - rem) != hm.get(rem))
return false;
}
}
return true;
}
// Driver code
public static void main(String[] args)
{
int arr[] = { 92, 75, 65, 48, 45, 35 };
int k = 10;
// Function call
boolean ans = canPairs(arr, k);
if (ans)
System.out.println("True");
else
System.out.println("False");
}
}
// This code is contributed by Rishabh Mahrsee
from collections import defaultdict
def can_pairs(arr, k):
n = len(arr)
# An odd length array cannot be divided into pairs
if n % 2 != 0:
return False
# Create a frequency map to count occurrences
# of all remainders when divided by k
freq = defaultdict(int)
for x in arr:
freq[(x % k + k) % k] += 1
# Traverse the array and check pairs
for x in arr:
rem = (x % k + k) % k
# If remainder divides k into two halves
if 2 * rem == k:
if freq[rem] % 2 != 0:
return False
# If remainder is 0, there must be an even count
elif rem == 0:
if freq[rem] % 2 != 0:
return False
# Else occurrences of remainder and
# k - remainder must match
elif freq[rem] != freq[k - rem]:
return False
return True
# Driver code
arr = [92, 75, 65, 48, 45, 35]
k = 10
print("True" if can_pairs(arr, k) else "False")
// C# program to check if arr[0..n-1]
// can be divided in pairs such that
// every pair is divisible by k.
using System.Collections.Generic;
using System;
class GFG {
// Returns true if arr[0..n-1] can be
// divided into pairs with sum
// divisible by k.
static bool canPairs(int[] ar, int k)
{
// An odd length array cannot
// be divided into pairs
if (ar.Length % 2 == 1)
return false;
// Create a frequency array to count
// occurrences of all remainders when
// divided by k.
Dictionary<Double, int> hm
= new Dictionary<Double, int>();
// Count occurrences of all remainders
for (int i = 0; i < ar.Length; i++) {
int rem = ((ar[i] % k) + k) % k;
if (!hm.ContainsKey(rem)) {
hm[rem] = 0;
}
hm[rem]++;
}
// Traverse input array and use freq[]
// to decide if given array can be
// divided in pairs
for (int i = 0; i < ar.Length; i++) {
// Remainder of current element
int rem = ((ar[i] % k) + k) % k;
// If remainder with current element
// divides k into two halves.
if (2 * rem == k) {
// Then there must be even occurrences
// of such remainder
if (hm[rem] % 2 == 1)
return false;
}
// If remainder is 0, then there
// must be two elements with 0
// remainder
else if (rem == 0) {
// Then there must be even occurrences
// of such remainder
if (hm[rem] % 2 == 1)
return false;
}
// Else number of occurrences of remainder
// must be equal to number of occurrences of
// k - remainder
else {
if (hm[k - rem] != hm[rem])
return false;
}
}
return true;
}
// Driver code
public static void Main()
{
int[] arr = { 92, 75, 65, 48, 45, 35 };
int k = 10;
bool ans = canPairs(arr, k);
if (ans)
Console.WriteLine("True");
else
Console.WriteLine("False");
}
}
function canPairs(arr, k) {
const n = arr.length;
// An odd length array cannot be divided into pairs
if (n % 2 !== 0) return false;
// Create a frequency map to count occurrences
// of all remainders when divided by k
const freq = new Map();
for (let x of arr) {
const rem = ((x % k) + k) % k;
freq.set(rem, (freq.get(rem) || 0) + 1);
}
// Traverse the array and check pairs
for (let x of arr) {
const rem = ((x % k) + k) % k;
// If remainder divides k into two halves
if (2 * rem === k) {
if ((freq.get(rem) || 0) % 2 !== 0) return false;
}
// If remainder is 0, there must be an even count
else if (rem === 0) {
if ((freq.get(rem) || 0) % 2 !== 0) return false;
}
// Else occurrences of remainder and k - remainder must match
else if ((freq.get(rem) || 0) !== (freq.get(k - rem) || 0)) {
return false;
}
}
return true;
}
// Driver code
const arr = [92, 75, 65, 48, 45, 35];
const k = 10;
console.log(canPairs(arr, k) ? "True" : "False");
Output
True
Efficient Approach for Small K - O(n) Time and O(k) Space
- In this approach we focus on the fact that if sum of two numbers mod K gives the output 0,then it is true for all instances that the individual number mod K would sum up to the K.
- We make an array of size K and there we increase the frequency and reduces it, if found a match and in the end if array has no element greater than 0 then it returns true else return false.
#include <bits/stdc++.h>
using namespace std;
bool canPairs(vector<int> arr, int k) {
if (arr.size() % 2 != 0)
return false;
vector<int> freq(k);
for (int x : arr) {
int rem = x % k;
// If the complement of the current
// remainder exists in freq, decrement its count
if (freq[(k - rem) % k] != 0)
freq[(k - rem) % k]--;
// Otherwise, increment the count of t
// he current remainder
else
freq[rem]++;
}
// Check if all elements in the frequency
// array are 0
for (int count : freq) {
if (count != 0)
return false;
}
return true;
}
int main() {
vector<int> arr = {92, 75, 65, 48, 45, 35};
int k = 10;
cout << (canPairs(arr, k) ? "True" : "False");
return 0;
}
import java.util.*;
public class Main {
public static boolean canPairs(int[] arr, int k) {
if (arr.length % 2 != 0)
return false;
// Create a frequency array of size k
int[] freq = new int[k];
for (int x : arr) {
int rem = x % k;
// If the complement of the current
// remainder exists in freq, decrement
// its count
if (freq[(k - rem) % k] != 0)
freq[(k - rem) % k]--;
// Otherwise, increment the count of
// the current remainder
else
freq[rem]++;
}
// Check if all elements in the frequency
// array are 0
for (int count : freq) {
if (count != 0)
return false;
}
return true;
}
public static void main(String[] args) {
int[] arr = {92, 75, 65, 48, 45, 35};
int k = 10;
System.out.println(canPairs(arr, k) ? "True" : "False");
}
}
def can_pairs(arr, k):
if len(arr) % 2 != 0:
return False
freq = [0] * k
for x in arr:
rem = x % k
# If the complement of the current
# remainder exists in freq, decrement its count
if freq[(k - rem) % k] != 0:
freq[(k - rem) % k] -= 1
# Otherwise, increment the count of the current remainder
else:
freq[rem] += 1
# Check if all elements in the frequency array are 0
for count in freq:
if count != 0:
return False
return True
arr = [92, 75, 65, 48, 45, 35]
k = 10
print("True" if can_pairs(arr, k) else "False")
using System;
using System.Linq;
class Program {
static bool CanPairs(int[] arr, int k) {
if (arr.Length % 2 != 0)
return false;
// Create a frequency array of size k
int[] freq = new int[k];
foreach (int x in arr) {
int rem = x % k;
// If the complement of the current
// remainder exists in freq, decrement
// its count
if (freq[(k - rem) % k] != 0)
freq[(k - rem) % k]--;
// Otherwise, increment the count of
// the current remainder
else
freq[rem]++;
}
// Check if all elements in the frequency array are 0
foreach (int count in freq) {
if (count != 0)
return false;
}
return true;
}
static void Main() {
int[] arr = {92, 75, 65, 48, 45, 35};
int k = 10;
Console.WriteLine(CanPairs(arr, k) ? "True" : "False");
}
}
function canPairs(arr, k) {
if (arr.length % 2 !== 0)
return false;
let freq = new Array(k).fill(0);
for (let x of arr) {
let rem = x % k;
// If the complement of the current
// remainder exists in freq, decrement
// its count
if (freq[(k - rem) % k] !== 0)
freq[(k - rem) % k]--;
// Otherwise, increment the count of
// the current remainder
else
freq[rem]++;
}
// Check if all elements in the
// frequency array are 0
for (let count of freq) {
if (count !== 0)
return false;
}
return true;
}
let arr = [92, 75, 65, 48, 45, 35];
let k = 10;
console.log(canPairs(arr, k) ? "True" : "False");
Output
True