Problem 914

Abstract / Summary

Given a deck of cards, determine if it is possible to rearrange the cards so that every rank appears the same number of times.

Note

The full problem description, including helpful examples, can be found on LeetCode.

Python 0914.py

class Solution:
    def hasGroupsSizeX(self, deck: List[int]) -> bool:
        if len(deck) == 1:
            return False

        freq = defaultdict(int)
        for d in deck:
            freq[d] += 1

        g = freq[deck[0]]
        # same greatest common divisor
        for f in freq.values():
            if f != g:
                g = gcd(g, f)
        return g > 1
15 lines | 391 bytes | submitted October 11, 2023 | GitHub   8% comment ratio | tab size 4 | low complexity

Difficulty

This problem is ranked as
easy medium hard

and has an acceptance rate of about 30% (400k+ submissions).

Typical patterns to solve this problem:
  • Array
  • Counting
  • Hash Table
  • Math
  • Number Theory
I solved 663 easy, 1250 medium and 309 hard problems

AI Disclaimer

Every single line of code was written by me, 100% from scratch, between August 2023 and August 2024.
However, two years later I set up this website and used various AI tools to generate most of the walkthrough / explanations below.

See this dedicated page for more details.
LeetCode profile | GitHub repo

Code Walkthrough

Overview

The provided implementation determines whether a deck of cards can be partitioned into groups of equal size X, where X ≥ 2 and each group contains identical card values. The algorithm proceeds by counting occurrences of each distinct card, then computing the greatest common divisor (GCD) of those counts. If the resulting GCD exceeds 1, a uniform group size exists; otherwise it does not.

Key Steps

The method begins with a guard clause that immediately rejects decks containing a single card, because a group size of at least 2 cannot be formed.

if len(deck) == 1:
    return False

Next, a frequency map is built using a defaultdict. This choice avoids explicit existence checks and guarantees constant-time updates for each element in the input list.

freq = defaultdict(int)
for d in deck:
    freq[d] += 1

The algorithm initializes the GCD accumulator with the count of the first card value. This avoids an extra pass to locate an arbitrary non-zero count.

g = freq[deck[0]]

A single loop then iterates over all frequency values. For each value that differs from the current accumulator, the gcd function is invoked to merge the new count into the running GCD. The conditional if f != g prevents unnecessary calls when the accumulator already matches the current frequency.

for f in freq.values():
    if f != g:
        g = gcd(g, f)

Finally, the method returns a boolean indicating whether the computed GCD is greater than 1, which directly corresponds to the existence of a valid group size.

return g > 1

Edge Cases Handled

When the deck consists of a single element, the early return ensures the function does not attempt to compute a GCD on a trivial frequency map.

If all cards are identical, the frequency map contains a single entry; the GCD accumulator is set to that count, and the loop does not modify it. The final comparison correctly identifies that any count ≥ 2 yields a true result.

When the deck contains multiple distinct values with frequencies that share a common divisor (for example, counts of 4, 8, 12), the iterative GCD computation collapses these numbers to their greatest common divisor (in this case 4), satisfying the condition g > 1.

Conversely, if the frequencies are co-prime (e.g., counts of 3 and 5), the GCD reduces to 1, and the method returns false, reflecting the impossibility of forming equal-sized groups larger than one.

Performance Optimizations

The use of defaultdict(int) eliminates the need for conditional checks during frequency accumulation, yielding a tight O(N) loop where N is the length of the deck.

Initializing the GCD with the first frequency avoids an extra traversal to locate a non-zero count, thereby saving constant-time overhead.

The conditional if f != g before invoking gcd reduces the number of expensive GCD calculations, especially in cases where many frequencies are identical to the current accumulator.

Overall, the algorithm performs a single pass to build the frequency map and a second pass over the distinct frequencies, resulting in linear time relative to the size of the input while using only a hash map for storage.

written by openai gpt

ELI5 - Simplified Explanation

Imagine a big pile of playing cards with different numbers on them. The goal is to sort these cards into small groups so that every single group has the exact same number of cards, and every group has cards with the same number written on them.

First, the code checks if there is only one card. If there is only one, it is impossible to make a group, so the game stops there. Next, the code looks at all the cards and counts how many of each number exist. It writes these counts down in a notebook to keep track.

After counting, the code looks at those numbers to see if they can be divided into equal piles. It uses a special math trick to find a common size that fits all the groups perfectly. If it finds that it can split all the cards into groups of at least two, it confirms that the cards can be arranged nicely. If the math shows that the groups cannot be made equal, then it says that it is not possible to organize the deck in that way.

written by google gemini

Code Quality

Several LLMs ranked my code quality on a scale from 1 (very poor) to 10 (outstanding):
n = 27 | median = 7 | μ = 7.19 | σ = 1.31

Complexity Analysis

not analyzed yet

Other Solutions

I wrote a basic crawler to find other solutions to that problem.
Obviously, I did that after I solved the problem myself.

In general, AlgoMonster and WalkCCC solutions are high-quality and always worth a look.
I haven't checked most of the other solutions, but they might be helpful as well.

And of course, the LeetCode forum is always a good place (or even the best) to look for alternative approaches.

(click on a column header to sort the table)
author
author solutions
www AlgoMonster C++ Python Java TS
WalkCCC C++ Python Java
leetcode.ca C++ Python Java Go TS
LeetcodeHelp C++ Python Java
Progiez C++ Python Java
github BigEggStudy C#
black-shadows C++
charles-wangkai Java
everthis JS
fengvyi C++
fsq C++
halfrost Go
haoel Python
JoshCrozier JS
keineahnung2345 C++
lkwq007 Python
lzl124631x C++
ruoru Rust
suxrobGM C#
varunu28 Java
AlgoMonster C++, Python, Java, TypeScript
WalkCCC C++, Python, Java
leetcode.ca C++, Go, Java, Python, TypeScript
LeetcodeHelp C++, Java, Python
Progiez C++, Java, Python
BigEggStudy C#
black-shadows C++, C++
charles-wangkai Java
everthis JavaScript
fengvyi C++
fsq C++
halfrost Go
haoel Python
JoshCrozier JavaScript
keineahnung2345 C++
lkwq007 Python
lzl124631x C++
ruoru Rust
suxrobGM C#
varunu28 Java
33 links | 20 authors | 8 languages

Videos

4 videos   did my crawler come up with invalid videos ? drop me a line.

Solved On The Same Day

16 solutions   October 11, 2023

Extra

There are a few extra pages giving you some insights into my setup:
  • Tech Stack - my development environment and tools
  • AI - how AI helped me create this website (NOT solving the problems)
  • Progress - progression over time
  • Quality - code quality