questions B (backspace - burst-balloons)
This commit is contained in:
179
backend/data/questions/best-poker-hand.yaml
Normal file
179
backend/data/questions/best-poker-hand.yaml
Normal file
@@ -0,0 +1,179 @@
|
||||
title: Best Poker Hand
|
||||
slug: best-poker-hand
|
||||
difficulty: easy
|
||||
leetcode_id: 2347
|
||||
leetcode_url: https://leetcode.com/problems/best-poker-hand/
|
||||
categories:
|
||||
- arrays
|
||||
- hash-tables
|
||||
patterns:
|
||||
- greedy
|
||||
|
||||
description: |
|
||||
You are given an integer array `ranks` and a character array `suits`. You have `5` cards where the i<sup>th</sup> card has a rank of `ranks[i]` and a suit of `suits[i]`.
|
||||
|
||||
The following are the types of **poker hands** you can make from best to worst:
|
||||
|
||||
1. `"Flush"`: Five cards of the same suit.
|
||||
2. `"Three of a Kind"`: Three cards of the same rank.
|
||||
3. `"Pair"`: Two cards of the same rank.
|
||||
4. `"High Card"`: Any single card.
|
||||
|
||||
Return *a string representing the **best** type of **poker hand** you can make with the given cards.*
|
||||
|
||||
**Note** that the return values are **case-sensitive**.
|
||||
|
||||
constraints: |
|
||||
- `ranks.length == suits.length == 5`
|
||||
- `1 <= ranks[i] <= 13`
|
||||
- `'a' <= suits[i] <= 'd'`
|
||||
- No two cards have the same rank and suit.
|
||||
|
||||
examples:
|
||||
- input: 'ranks = [13,2,3,1,9], suits = ["a","a","a","a","a"]'
|
||||
output: '"Flush"'
|
||||
explanation: "The hand with all the cards consists of 5 cards with the same suit, so we have a \"Flush\"."
|
||||
- input: 'ranks = [4,4,2,4,4], suits = ["d","a","a","b","c"]'
|
||||
output: '"Three of a Kind"'
|
||||
explanation: "The hand with the first, second, and fourth card consists of 3 cards with the same rank, so we have a \"Three of a Kind\". Note that we could also make a \"Pair\" hand but \"Three of a Kind\" is a better hand."
|
||||
- input: 'ranks = [10,10,2,12,9], suits = ["a","b","c","a","d"]'
|
||||
output: '"Pair"'
|
||||
explanation: "The hand with the first and second card consists of 2 cards with the same rank, so we have a \"Pair\". Note that we cannot make a \"Flush\" or a \"Three of a Kind\"."
|
||||
|
||||
explanation:
|
||||
intuition: |
|
||||
Think of this problem like a poker player evaluating their hand. You're dealt 5 cards and need to identify the **best possible hand** you can claim.
|
||||
|
||||
The key insight is that the hand types are ordered from best to worst, so we should check for them **in that order**. As soon as we find a match, we can return immediately — no need to check lesser hands.
|
||||
|
||||
For a Flush, we need all 5 cards to share the same suit. This is easy to check: if there's only one unique suit among all cards, it's a Flush.
|
||||
|
||||
For Three of a Kind or Pair, we need to count how many times each rank appears. The **maximum frequency** of any rank tells us our best option:
|
||||
- If any rank appears 3+ times → "Three of a Kind"
|
||||
- If any rank appears exactly 2 times → "Pair"
|
||||
- Otherwise → "High Card"
|
||||
|
||||
The problem is simplified by the fixed hand size of 5 cards, which means we can use simple counting with hash tables.
|
||||
|
||||
approach: |
|
||||
We solve this using a **Priority Check with Counting** approach:
|
||||
|
||||
**Step 1: Check for Flush**
|
||||
|
||||
- Count the unique suits in the `suits` array
|
||||
- If there's only 1 unique suit, all 5 cards match → return `"Flush"`
|
||||
- We can use a set to find unique elements efficiently
|
||||
|
||||
|
||||
|
||||
**Step 2: Count rank frequencies**
|
||||
|
||||
- Use a hash map (Counter/dictionary) to count occurrences of each rank
|
||||
- Find the maximum frequency among all ranks
|
||||
|
||||
|
||||
|
||||
**Step 3: Determine hand based on max frequency**
|
||||
|
||||
- If `max_count >= 3` → return `"Three of a Kind"`
|
||||
- If `max_count == 2` → return `"Pair"`
|
||||
- Otherwise → return `"High Card"`
|
||||
|
||||
|
||||
|
||||
This greedy approach works because we check hands in order of priority. The moment we find a qualifying hand, we return it — guaranteeing we report the best possible hand.
|
||||
|
||||
common_pitfalls:
|
||||
- title: Checking in Wrong Order
|
||||
description: |
|
||||
A common mistake is checking for Pair before Three of a Kind, or checking ranks before suits.
|
||||
|
||||
The problem states the hand types from best to worst. If you have four cards of the same rank (like `[4,4,4,4,2]`), that qualifies as both "Three of a Kind" and "Pair". You must return "Three of a Kind" because it's ranked higher.
|
||||
|
||||
Always check in priority order: Flush → Three of a Kind → Pair → High Card.
|
||||
wrong_approach: "Check for Pair before Three of a Kind"
|
||||
correct_approach: "Check hands in order of priority (best to worst)"
|
||||
|
||||
- title: Overcomplicating the Flush Check
|
||||
description: |
|
||||
Some solutions iterate through the suits array comparing elements when a simpler approach exists.
|
||||
|
||||
Since we have exactly 5 cards and 5 suits, checking if all suits are the same is equivalent to checking if there's only 1 unique suit. Using `len(set(suits)) == 1` is cleaner and more Pythonic.
|
||||
wrong_approach: "Loop comparing suits[i] == suits[0] for all i"
|
||||
correct_approach: "Use len(set(suits)) == 1"
|
||||
|
||||
- title: Missing the Four of a Kind Case
|
||||
description: |
|
||||
The problem doesn't list "Four of a Kind" as a separate hand type. When you have 4 cards of the same rank, it still only counts as "Three of a Kind" per the problem definition.
|
||||
|
||||
Don't add extra logic for four-of-a-kind — the `max_count >= 3` check handles it correctly by returning "Three of a Kind".
|
||||
|
||||
key_takeaways:
|
||||
- "**Priority-based evaluation**: When categorising into ranked tiers, check from best to worst and return on first match"
|
||||
- "**Hash tables for counting**: `Counter` or dictionaries make frequency counting trivial — finding max frequency is O(n)"
|
||||
- "**Sets for uniqueness**: Converting to a set instantly tells you how many unique elements exist"
|
||||
- "**Fixed input size**: With only 5 cards, even 'inefficient' approaches are fast — but clean code still matters"
|
||||
|
||||
time_complexity: "O(1). We process exactly 5 cards, making this effectively constant time regardless of implementation details."
|
||||
space_complexity: "O(1). The hash map stores at most 5 entries (one per card), and the set stores at most 4 suits — both bounded by constants."
|
||||
|
||||
solutions:
|
||||
- approach_name: Priority Check with Counting
|
||||
is_optimal: true
|
||||
code: |
|
||||
from collections import Counter
|
||||
|
||||
def best_hand(ranks: list[int], suits: list[str]) -> str:
|
||||
# Check for Flush: all 5 cards same suit
|
||||
if len(set(suits)) == 1:
|
||||
return "Flush"
|
||||
|
||||
# Count frequency of each rank
|
||||
rank_counts = Counter(ranks)
|
||||
max_count = max(rank_counts.values())
|
||||
|
||||
# Check for Three of a Kind (3 or more of same rank)
|
||||
if max_count >= 3:
|
||||
return "Three of a Kind"
|
||||
|
||||
# Check for Pair (exactly 2 of same rank)
|
||||
if max_count == 2:
|
||||
return "Pair"
|
||||
|
||||
# Default: High Card
|
||||
return "High Card"
|
||||
explanation: |
|
||||
**Time Complexity:** O(1) — We always process exactly 5 cards.
|
||||
|
||||
**Space Complexity:** O(1) — Counter and set are bounded by the fixed hand size.
|
||||
|
||||
We check for each hand type in order of priority. The Flush check uses a set for O(1) uniqueness counting. The Counter gives us rank frequencies, and we only need the maximum to determine Three of a Kind vs Pair vs High Card.
|
||||
|
||||
- approach_name: Manual Counting (No Imports)
|
||||
is_optimal: false
|
||||
code: |
|
||||
def best_hand(ranks: list[int], suits: list[str]) -> str:
|
||||
# Check for Flush: compare all suits to the first
|
||||
is_flush = all(s == suits[0] for s in suits)
|
||||
if is_flush:
|
||||
return "Flush"
|
||||
|
||||
# Count rank frequencies using a dictionary
|
||||
rank_counts = {}
|
||||
for rank in ranks:
|
||||
rank_counts[rank] = rank_counts.get(rank, 0) + 1
|
||||
|
||||
# Find max frequency
|
||||
max_count = max(rank_counts.values())
|
||||
|
||||
if max_count >= 3:
|
||||
return "Three of a Kind"
|
||||
if max_count == 2:
|
||||
return "Pair"
|
||||
return "High Card"
|
||||
explanation: |
|
||||
**Time Complexity:** O(1) — Fixed 5-card input.
|
||||
|
||||
**Space Complexity:** O(1) — Dictionary bounded by hand size.
|
||||
|
||||
This version avoids importing `Counter` by manually building a frequency dictionary. The `all()` function provides a readable Flush check. Functionally equivalent to the optimal solution, just more verbose.
|
||||
Reference in New Issue
Block a user