🧠
Optimal Approach Using Hash Map for Frequency Counting
💡 This approach uses a hash map instead of an array to handle large or sparse k values and negative numbers more flexibly.
Intuition
Use a hash map to count frequencies of remainders mod k, then verify complementary remainder counts match for pairing.
Algorithm
- Return false if array length is odd.
- Create a hash map to count frequencies of nums[i] % k, adjusting modulo for negatives.
- Check if frequency of remainder 0 is even.
- For each remainder r in the map (excluding 0), check if freq[r] equals freq[k-r].
- If k is even, check freq[k/2] is even.
- Return true if all conditions hold.
💡 This approach generalizes the frequency array method to handle any k and negative values robustly.
def canArrange(nums, k):
if len(nums) % 2 != 0:
return False
freq = {}
for num in nums:
r = ((num % k) + k) % k # Adjust modulo for negative numbers
freq[r] = freq.get(r, 0) + 1
if freq.get(0, 0) % 2 != 0:
return False
for r in freq:
if r != 0:
complement = (k - r) % k
if freq.get(r, 0) != freq.get(complement, 0):
return False
if k % 2 == 0 and freq.get(k // 2, 0) % 2 != 0:
return False
return True
# Driver code
if __name__ == '__main__':
print(canArrange([1,2,3,4,5,10,6,7,8,9], 5)) # True
print(canArrange([1,2,3,4,5,6], 7)) # True
print(canArrange([1,2,3,4,5], 3)) # False
Line Notes
freq = {}Use dictionary to count remainder frequencies dynamically
r = ((num % k) + k) % k # Adjust modulo for negative numbersCalculate remainder for each element, handling negatives correctly
freq[r] = freq.get(r, 0) + 1Increment frequency count safely
if freq.get(0, 0) % 2 != 0:Check even count for remainder zero elements
import java.util.*;
public class Solution {
public static boolean canArrange(int[] nums, int k) {
if (nums.length % 2 != 0) return false;
Map<Integer, Integer> freq = new HashMap<>();
for (int num : nums) {
int r = ((num % k) + k) % k;
freq.put(r, freq.getOrDefault(r, 0) + 1);
}
if (freq.getOrDefault(0, 0) % 2 != 0) return false;
for (int r : freq.keySet()) {
if (r != 0) {
int complement = (k - r) % k;
if (!freq.getOrDefault(r, 0).equals(freq.getOrDefault(complement, 0))) return false;
}
}
if (k % 2 == 0 && freq.getOrDefault(k / 2, 0) % 2 != 0) return false;
return true;
}
public static void main(String[] args) {
System.out.println(canArrange(new int[]{1,2,3,4,5,10,6,7,8,9}, 5)); // true
System.out.println(canArrange(new int[]{1,2,3,4,5,6}, 7)); // true
System.out.println(canArrange(new int[]{1,2,3,4,5}, 3)); // false
}
}
Line Notes
Map<Integer, Integer> freq = new HashMap<>();Use hash map for flexible remainder frequency counting
int r = ((num % k) + k) % k;Modulo adjusted for negative numbers
freq.put(r, freq.getOrDefault(r, 0) + 1);Increment frequency safely
if (freq.getOrDefault(0, 0) % 2 != 0) return false;Check even count for remainder zero
#include <iostream>
#include <vector>
#include <unordered_map>
using namespace std;
bool canArrange(vector<int>& nums, int k) {
int n = nums.size();
if (n % 2 != 0) return false;
unordered_map<int, int> freq;
for (int num : nums) {
int r = ((num % k) + k) % k;
freq[r]++;
}
if (freq[0] % 2 != 0) return false;
for (auto& p : freq) {
int r = p.first;
if (r != 0) {
int complement = (k - r) % k;
if (freq[r] != freq[complement]) return false;
}
}
if (k % 2 == 0 && freq[k / 2] % 2 != 0) return false;
return true;
}
int main() {
vector<int> nums1 = {1,2,3,4,5,10,6,7,8,9};
cout << (canArrange(nums1, 5) ? "true" : "false") << endl; // true
vector<int> nums2 = {1,2,3,4,5,6};
cout << (canArrange(nums2, 7) ? "true" : "false") << endl; // true
vector<int> nums3 = {1,2,3,4,5};
cout << (canArrange(nums3, 3) ? "true" : "false") << endl; // false
return 0;
}
Line Notes
unordered_map<int, int> freq;Hash map for remainder frequency counting
int r = ((num % k) + k) % k;Modulo adjusted for negative numbers
freq[r]++;Increment frequency count
if (freq[0] % 2 != 0) return false;Check even count for remainder zero
function canArrange(nums, k) {
if (nums.length % 2 !== 0) return false;
const freq = new Map();
for (const num of nums) {
let r = ((num % k) + k) % k;
freq.set(r, (freq.get(r) || 0) + 1);
}
if ((freq.get(0) || 0) % 2 !== 0) return false;
for (const r of freq.keys()) {
if (r !== 0) {
const complement = (k - r) % k;
if ((freq.get(r) || 0) !== (freq.get(complement) || 0)) return false;
}
}
if (k % 2 === 0 && ((freq.get(k / 2) || 0) % 2 !== 0)) return false;
return true;
}
// Test cases
console.log(canArrange([1,2,3,4,5,10,6,7,8,9], 5)); // true
console.log(canArrange([1,2,3,4,5,6], 7)); // true
console.log(canArrange([1,2,3,4,5], 3)); // false
Line Notes
const freq = new Map();Use Map for flexible remainder frequency counting
let r = ((num % k) + k) % k;Modulo adjusted for negative numbers
freq.set(r, (freq.get(r) || 0) + 1);Increment frequency count safely
if ((freq.get(0) || 0) % 2 !== 0) return false;Check even count for remainder zero
We iterate over nums once and use a hash map for frequencies. Checking pairs is O(n) in worst case.
💡 This approach is efficient even if k is large or sparse, and handles negative numbers gracefully.
Interview Verdict: Accepted
This is the most general and robust solution, suitable for all inputs.