Hand of Straights medium
Problem Statement
You are given an integer array hand
representing the cards you hold. You want to check if you can form a group
of W
consecutive cards. A group consists of W
cards of consecutive denominations.
Given an integer W
representing the number of consecutive cards in a group, return true
if you can form such a group, otherwise return false
.
Example 1
Input: hand = [1,2,3,6,2,3,4,7,8], W = 3 Output: true Explanation: We can form two groups of 3 consecutive cards: [1,2,3] and [6,7,8].
Example 2
Input: hand = [1,2,3,4,5], W = 4 Output: false Explanation: We cannot form any group of 4 consecutive cards.
Steps
- Sort the hand: Sorting the hand allows us to easily identify consecutive cards.
- Count card frequencies: Use a map to count the frequency of each card.
- Iterate and check for groups: Iterate through the sorted hand. For each card, check if we can form a group of
W
consecutive cards starting from that card. If we can, decrement the frequencies of the cards in the group. If we cannot, returnfalse
. - Return true if all cards are used: If the loop completes without returning
false
, it means we successfully formed groups for all cards, so we returntrue
.
Explanation
The core idea is to efficiently check for consecutive sequences. Sorting allows for a linear scan. The frequency map avoids redundant counting and allows for quick checks of card availability. The algorithm systematically tries to build groups of size W
, ensuring that no card is used more times than it exists. If at any point it's impossible to form a group (because a necessary card is missing or its frequency is insufficient), the function immediately returns false
.
Code
#include <iostream>
#include <vector>
#include <map>
#include <algorithm>
using namespace std;
bool isNStraightHand(vector<int>& hand, int W) {
if (hand.size() % W != 0) return false; // Cannot form groups if size is not a multiple of W
map<int, int> counts;
for (int card : hand) {
counts[card]++;
}
sort(hand.begin(), hand.end());
for (int card : hand) {
if (counts[card] == 0) continue; // Skip already used cards
for (int i = 0; i < W; ++i) {
if (counts.find(card + i) == counts.end() || counts[card + i] == 0) {
return false; // Missing card or insufficient frequency
}
counts[card + i]--;
}
}
return true;
}
int main() {
vector<int> hand1 = {1, 2, 3, 6, 2, 3, 4, 7, 8};
int W1 = 3;
cout << "Example 1: " << isNStraightHand(hand1, W1) << endl; // Output: true
vector<int> hand2 = {1, 2, 3, 4, 5};
int W2 = 4;
cout << "Example 2: " << isNStraightHand(hand2, W2) << endl; // Output: false
return 0;
}
Complexity
- Time Complexity: O(N log N), where N is the number of cards in
hand
. This is dominated by the sorting step. The map operations (insertion and lookup) have amortized O(1) time complexity. - Space Complexity: O(N) in the worst case, to store the frequency map. The sorted hand is done in-place for the solution presented, therefore, not adding to space complexity.