from collections import Counter
class Solution:
def canArrange(self, arr, k):
count = Counter()
for num in arr:
remainder = num % k
count[remainder] += 1
for rem in count:
if rem == 0:
if count[rem] % 2 != 0:
return False
elif 2 * rem == k:
if count[rem] % 2 != 0:
return False
else:
if count[rem] != count[k - rem]:
return False
return True
#include <vector>
#include <unordered_map>
using namespace std;
class Solution {
public:
bool canArrange(vector<int>& arr, int k) {
unordered_map<int, int> count;
for (int num : arr) {
int rem = ((num % k) + k) % k;
count[rem]++;
}
for (auto it : count) {
int rem = it.first;
if (rem == 0) {
if (count[rem] % 2 != 0) return false;
} else if (2 * rem == k) {
if (count[rem] % 2 != 0) return false;
} else {
if (count[rem] != count[k - rem]) return false;
}
}
return true;
}
};
import java.util.*;
class Solution {
public boolean canArrange(int[] arr, int k) {
Map<Integer, Integer> count = new HashMap<>();
for (int num : arr) {
int rem = ((num % k) + k) % k;
count.put(rem, count.getOrDefault(rem, 0) + 1);
}
for (int rem : count.keySet()) {
if (rem == 0) {
if (count.get(rem) % 2 != 0) return false;
} else if (2 * rem == k) {
if (count.get(rem) % 2 != 0) return false;
} else {
if (!count.get(rem).equals(count.getOrDefault(k - rem, 0))) return false;
}
}
return true;
}
}
var canArrange = function(arr, k) {
let count = new Map();
for (let num of arr) {
let rem = ((num % k) + k) % k;
count.set(rem, (count.get(rem) || 0) + 1);
}
for (let [rem, val] of count.entries()) {
if (rem === 0) {
if (val % 2 !== 0) return false;
} else if (2 * rem === k) {
if (val % 2 !== 0) return false;
} else {
if (val !== (count.get(k - rem) || 0)) return false;
}
}
return true;
};
Given an array of integers arr
and an integer k
, determine if it is possible to rearrange the elements of arr
into pairs such that the sum of each pair is divisible by k
. Each element in arr
must be used exactly once, and each pair must consist of two distinct (not necessarily different) elements from the array.
k
.true
; otherwise, return false
.
At first glance, it may seem that we need to try all possible pairings, checking if each pair sums to a multiple of k
. However, this brute-force approach is inefficient and impractical for large arrays.
To optimize, we should focus on the remainders of the numbers when divided by k
. If two numbers have remainders r1
and r2
, their sum is divisible by k
if and only if (r1 + r2) % k == 0
. This means r2 = k - r1
(or both are zero).
So, instead of checking all pairs, we can count how many numbers have each possible remainder, and then check if the counts can be paired up appropriately.
arr
when divided by k
. For negative numbers, adjust the remainder to be in the range 0
to k-1
.rem
:
rem == 0
: There must be an even number of such elements, since they must pair with each other.2 * rem == k
(when k
is even): These remainders must also be paired among themselves, so their count must be even.rem
must equal the count with remainder k - rem
, because each such pair together sums to a multiple of k
.true
. Otherwise, return false
.We use a hash map for efficient counting and lookups, ensuring the algorithm runs in linear time.
Example: arr = [1,2,3,4,5,10,6,7,8,9]
, k = 5
true
.The array can be paired as (1,4), (2,3), (5,10), (6,9), (7,8) where each pair sums to a multiple of 5.
arr
. We scan the array once to compute remainders and once to check the pairing conditions.The optimized approach is efficient and suitable for large inputs.
By focusing on the remainders of each element modulo k
and counting their frequencies, we reduce the problem of pairwise matching to a simple counting problem. The key insight is that for each remainder, there must be a matching count of its complement to form valid pairs. This leads to a clean and efficient solution that avoids brute-force enumeration, making the algorithm both elegant and performant.