Before attempting this problem, you should be comfortable with:
Hash Maps - Counting element frequencies efficiently in O(1) per operation
Hash Sets - Tracking elements with odd occurrences using add/remove toggle logic
Sorting - Grouping identical elements together for run-length analysis
1. Sorting
Intuition
For an array to be divisible into pairs of equal elements, every distinct value must appear an even number of times. By sorting the array, identical elements become adjacent. We can then scan through and count consecutive runs of equal values. If any run has an odd length, we cannot form valid pairs.
Algorithm
Sort the array.
Iterate through the sorted array, tracking runs of consecutive equal elements.
classSolution:defdivideArray(self, nums: List[int])->bool:
N =len(nums)
nums.sort()
i =0while i < N:
j = i
while j < N and nums[i]== nums[j]:
j +=1if(j - i)%2!=0:returnFalse
i = j
returnTrue
publicclassSolution{publicbooleandivideArray(int[] nums){intN= nums.length;Arrays.sort(nums);int i =0;while(i <N){int j = i;while(j <N&& nums[i]== nums[j]){
j++;}if((j - i)%2!=0){returnfalse;}
i = j;}returntrue;}}
classSolution{public:booldivideArray(vector<int>& nums){int N = nums.size();sort(nums.begin(), nums.end());int i =0;while(i < N){int j = i;while(j < N && nums[i]== nums[j]){
j++;}if((j - i)%2!=0){returnfalse;}
i = j;}returntrue;}};
classSolution{/**
* @param {number[]} nums
* @return {boolean}
*/divideArray(nums){constN= nums.length;
nums.sort((a, b)=> a - b);let i =0;while(i <N){let j = i;while(j <N&& nums[i]=== nums[j]){
j++;}if((j - i)%2!==0){returnfalse;}
i = j;}returntrue;}}
publicclassSolution{publicboolDivideArray(int[] nums){int N = nums.Length;
Array.Sort(nums);int i =0;while(i < N){int j = i;while(j < N && nums[i]== nums[j]){
j++;}if((j - i)%2!=0){returnfalse;}
i = j;}returntrue;}}
funcdivideArray(nums []int)bool{
N :=len(nums)
sort.Ints(nums)
i :=0for i < N {
j := i
for j < N && nums[i]== nums[j]{
j++}if(j-i)%2!=0{returnfalse}
i = j
}returntrue}
class Solution {fundivideArray(nums: IntArray): Boolean {val N = nums.size
nums.sort()var i =0while(i < N){var j = i
while(j < N && nums[i]== nums[j]){
j++}if((j - i)%2!=0){returnfalse}
i = j
}returntrue}}
classSolution{funcdivideArray(_ nums:[Int])->Bool{letN= nums.count
let nums = nums.sorted()var i =0while i <N{var j = i
while j <N&& nums[i]== nums[j]{
j +=1}if(j - i)%2!=0{returnfalse}
i = j
}returntrue}}
Time & Space Complexity
Time complexity: O(nlogn)
Space complexity: O(1) or O(n) depending on the sorting algorithm.
2. Hash Map
Intuition
We can count the frequency of each element using a hash map. After counting, we check if every element appears an even number of times. If any element has an odd count, it cannot be fully paired, so we return false.
Algorithm
Create a hash map to store the count of each element.
Iterate through the array and increment the count for each element.
classSolution:defdivideArray(self, nums: List[int])->bool:
count ={}for num in nums:if num notin count:
count[num]=0
count[num]+=1for cnt in count.values():if cnt %2==1:returnFalsereturnTrue
classSolution{/**
* @param {number[]} nums
* @return {boolean}
*/divideArray(nums){const count ={};for(let num of nums){if(!(num in count)){
count[num]=0;}
count[num]++;}for(let key in count){if(count[key]%2===1){returnfalse;}}returntrue;}}
publicclassSolution{publicboolDivideArray(int[] nums){Dictionary<int,int> count =newDictionary<int,int>();foreach(int num in nums){if(!count.ContainsKey(num)){
count[num]=0;}
count[num]++;}foreach(var cnt in count.Values){if(cnt %2==1){returnfalse;}}returntrue;}}
class Solution {fundivideArray(nums: IntArray): Boolean {val count = HashMap<Int, Int>()for(num in nums){
count[num]= count.getOrDefault(num,0)+1}for(cnt in count.values){if(cnt %2==1){returnfalse}}returntrue}}
classSolution{funcdivideArray(_ nums:[Int])->Bool{var count =[Int:Int]()for num in nums {
count[num,default:0]+=1}for cnt in count.values {if cnt %2==1{returnfalse}}returntrue}}
Time & Space Complexity
Time complexity: O(n)
Space complexity: O(n)
3. Hash Set
Intuition
Instead of counting all frequencies, we can use a set to track elements with odd occurrences. When we see an element, if it is already in the set (meaning we have seen it an odd number of times), we remove it. If it is not in the set, we add it. At the end, if the set is empty, all elements appeared an even number of times.
Algorithm
Create an empty hash set.
Iterate through each element in the array.
If the element is in the set, remove it (completing a pair).
Otherwise, add it to the set (unpaired element).
After processing all elements, return true if the set is empty, false otherwise.
classSolution:defdivideArray(self, nums: List[int])->bool:
odd_set =set()for num in nums:if num notin odd_set:
odd_set.add(num)else:
odd_set.remove(num)returnnotlen(odd_set)
publicclassSolution{publicbooleandivideArray(int[] nums){Set<Integer> oddSet =newHashSet<>();for(int num : nums){if(!oddSet.contains(num)){
oddSet.add(num);}else{
oddSet.remove(num);}}return oddSet.isEmpty();}}
classSolution{public:booldivideArray(vector<int>& nums){
unordered_set<int> oddSet;for(int num : nums){if(oddSet.count(num)){
oddSet.erase(num);}else{
oddSet.insert(num);}}return oddSet.empty();}};
classSolution{/**
* @param {number[]} nums
* @return {boolean}
*/divideArray(nums){const oddSet =newSet();for(let num of nums){if(oddSet.has(num)){
oddSet.delete(num);}else{
oddSet.add(num);}}return oddSet.size ===0;}}
publicclassSolution{publicboolDivideArray(int[] nums){HashSet<int> oddSet =newHashSet<int>();foreach(int num in nums){if(oddSet.Contains(num)){
oddSet.Remove(num);}else{
oddSet.Add(num);}}return oddSet.Count ==0;}}
class Solution {fundivideArray(nums: IntArray): Boolean {val oddSet = HashSet<Int>()for(num in nums){if(num in oddSet){
oddSet.remove(num)}else{
oddSet.add(num)}}return oddSet.isEmpty()}}
classSolution{funcdivideArray(_ nums:[Int])->Bool{var oddSet =Set<Int>()for num in nums {if oddSet.contains(num){
oddSet.remove(num)}else{
oddSet.insert(num)}}return oddSet.isEmpty
}}
Time & Space Complexity
Time complexity: O(n)
Space complexity: O(n)
Common Pitfalls
Checking for Pairs Instead of Even Counts
A common mistake is trying to actually form pairs and check if adjacent elements match after sorting. The problem only requires checking if each element appears an even number of times, not that the pairs are adjacent.
# Wrong: Checking adjacent pairs after sorting
nums.sort()for i inrange(0,len(nums),2):if nums[i]!= nums[i +1]:# IndexError if odd lengthreturnFalse# Correct: Just check if each count is evenfor cnt in count.values():if cnt %2==1:returnFalse
Forgetting the Array Length is Always Even
The problem guarantees that nums has 2n elements. Some solutions add unnecessary checks for odd-length arrays or forget that the total count of elements is always even, which simplifies the problem to just checking individual element frequencies.