Best Poker Hand

Easy
#2137Time: O(1) - The number of cards is fixed at 5. All loops run a constant number of times.Space: O(1) - The `HashSet` and `HashMap` will store at most 5 elements, as the input size is fixed.
Patterns
Data structures

Prompt

You are given an integer array ranks and a character array suits. You have 5 cards where the ith 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.

 

Example 1:

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".

Example 2:

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.
Also note that other cards could be used to make the "Three of a Kind" hand.

Example 3:

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".

 

Constraints:

  • ranks.length == suits.length == 5
  • 1 <= ranks[i] <= 13
  • 'a' <= suits[i] <= 'd'
  • No two cards have the same rank and suit.

Approaches

3 approaches with complexity analysis and trade-offs.

This approach directly translates the rules into code using standard Java collections. It first checks for a "Flush" by seeing if all suits are the same. A HashSet is a natural choice for this; if all 5 suits are added to a set and the final size is 1, it's a flush. If it's not a flush, it then checks for rank-based hands ("Three of a Kind", "Pair"). A HashMap is used to count the occurrences of each rank. By iterating through the counts in the map, we can determine if there's a group of 3 or 2. The checks are performed in order of hand strength to ensure the best hand is always returned.

Algorithm

  • Check for Flush:
    • Create a HashSet<Character>.
    • Iterate through the suits array and add each suit to the set.
    • If the size of the set is 1, it's a flush. Return "Flush".
  • Count Ranks:
    • If it's not a flush, create a HashMap<Integer, Integer> to store the frequency of each card rank.
    • Iterate through the ranks array, and for each rank, update its count in the map.
  • Check for Three of a Kind or Pair:
    • Initialize a boolean flag, hasPair, to false.
    • Iterate through the values (counts) of the HashMap.
      • If any count is 3 or greater, we have found a "Three of a Kind". Return "Three of a Kind".
      • If any count is 2, we have found a pair. Set hasPair = true.
  • Determine Final Hand:
    • After checking all rank counts, if the hasPair flag is true, return "Pair".
  • Default to High Card:
    • If the function has not returned yet, return "High Card".

Walkthrough

The logic is broken down into sequential checks based on the hierarchy of poker hands.

  1. Flush Check: We use a HashSet to efficiently determine if all suits are identical. Adding all five suits to a set will result in a set of size 1 if and only if they are all the same.
  2. Rank Counting: If the hand is not a flush, we need to analyze the ranks. A HashMap is used to count the frequency of each rank. We iterate through the ranks array and store the counts in the map.
  3. Hand Evaluation: We then iterate through the frequency counts stored in the map's values. Since we must return the best hand, we check for "Three of a Kind" first. If any rank appears 3 or more times, we immediately return. If not, we check for a "Pair". A boolean flag hasPair tracks if we've seen any rank appear twice.
  4. Final Result: After checking all rank frequencies, if we found a pair (and not a three of a kind), we return "Pair". If neither of these conditions is met, the hand is a "High Card".
import java.util.HashMap;import java.util.HashSet;import java.util.Map;import java.util.Set; class Solution {    public String bestHand(int[] ranks, char[] suits) {        // 1. Check for Flush        Set<Character> suitSet = new HashSet<>();        for (char suit : suits) {            suitSet.add(suit);        }        if (suitSet.size() == 1) {            return "Flush";        }         // 2. Count Ranks        Map<Integer, Integer> rankCounts = new HashMap<>();        for (int rank : ranks) {            rankCounts.put(rank, rankCounts.getOrDefault(rank, 0) + 1);        }         // 3. Check for Three of a Kind or Pair        boolean hasPair = false;        for (int count : rankCounts.values()) {            if (count >= 3) {                return "Three of a Kind";            }            if (count == 2) {                hasPair = true;            }        }         // 4. Determine Final Hand        if (hasPair) {            return "Pair";        }         // 5. Default to High Card        return "High Card";    }}

Complexity

Time

O(1) - The number of cards is fixed at 5. All loops run a constant number of times.

Space

O(1) - The `HashSet` and `HashMap` will store at most 5 elements, as the input size is fixed.

Trade-offs

Pros

  • The code is highly readable and directly maps to the problem's logic.

  • It's a general approach that would work even if the range of ranks was large or non-contiguous.

Cons

  • HashMap and HashSet have some performance overhead compared to using arrays, especially for a small, fixed range of integer keys.

  • This approach may involve multiple passes over the data or data structures, making it slightly less efficient than a single-pass solution.

Solutions

class Solution {public  String bestHand(int[] ranks, char[] suits) {    boolean flush = true;    for (int i = 1; i < 5 && flush; ++i) {      flush = suits[i] == suits[i - 1];    }    if (flush) {      return "Flush";    }    int[] cnt = new int[14];    boolean pair = false;    for (int x : ranks) {      if (++cnt[x] == 3) {        return "Three of a Kind";      }      pair = pair || cnt[x] == 2;    }    return pair ? "Pair" : "High Card";  }}

Video walkthrough

Newsletter

One sharp idea, every week

System design and interview prep — short enough to finish.

No spam. Unsubscribe anytime.

Practice

Same difficulty — related problems to reinforce the pattern.