Alice has a hand of cards, given as an array of integers.
Now she wants to rearrange the cards into groups so that each group is size W, and consists of W consecutive cards.
Return true if and only if she can.
 


Example 1:
Input: hand = [1,2,3,6,2,3,4,7,8], W = 3
Output: true
Explanation: Alice's hand can be rearranged as [1,2,3],[2,3,4],[6,7,8].
Example 2:
Input: hand = [1,2,3,4,5], W = 4
Output: false
Explanation: Alice's hand can't be rearranged into groups of 4.

 
Constraints:

1 <= hand.length <= 10000
0 <= hand[i] <= 10^9
1 <= W <= hand.length

Note: This question is the same as 1296: https://leetcode.com/problems/divide-array-in-sets-of-k-consecutive-numbers/

Difficulty: interview

Starter code:

class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        

Solutions:
class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        # 1, 2, 2, 3, 3, 4, 6, 7, 8
        # 1 2 3
        #   2 3 4
        #         6 7 8
        
        # W length Q
        # how many opened
        # # of the element is current opened one
        
        q = deque()
        opened = 0
        last = 0
        counter = Counter(hand)
        for n in sorted(counter):
            count = counter[n]
            if n > last + 1 and opened > 0:
                return False
            
            if n == last + 1 and count < opened:
                return False
            
            
            q.append(count - opened)
            opened = count
            
            if len(q) == W:
                opened -= q.popleft()
            
            last = n
        return not opened

class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        if len(hand) % W != 0:
            return False
        
        counter = collections.Counter(hand)
        
        for num in hand:
            if counter[num - 1] > 0 or counter[num] == 0:
                continue
                
            curr = num
            cnt = 0
            while cnt < W:
                if counter[curr] == 0:
                    return False
                counter[curr] -= 1
                curr += 1
                cnt += 1
        
        return True

class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        if len(hand)%W != 0:
            return False
        heap = [(key,val) for key,val in list(Counter(hand).items())]
        heapq.heapify(heap)
        while heap:
            pre,prec = None, None
            temp = deque()
            for _ in range(W):
                if not heap:
                    return False
                num,count = heapq.heappop(heap)
                if not pre:
                    pre,prec = num,count
                    continue
                if num != pre+1 or count < prec:
                    return False
                pre = num
                if count > prec:
                    temp.append((num,count-prec))
            while temp:
                heapq.heappush(heap,temp.pop())
        return True


from collections import Counter
class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        count = Counter(hand)
        while count:
            key = min(count)
            for k in range(key, key+W):
                check = count[k]
                if not check:
                    return False
                else:
                    count[k] -= 1
                if check == 1:
                    del count[k]
        return True

from collections import Counter

class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        N = len(hand)
        if N%W != 0:
            return False
                
        counter = Counter(hand)
        while counter:
            first = min(counter.keys())
            for i in range(first, first+W):
                if i not in counter:
                    return False
                counter[i] -= 1
                if counter[i] == 0:
                    del counter[i]
                    
        return True

class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        c = Counter(hand)
        while c:
            x = min(c.keys())
            for i in range(x,x+W):
                if i not in c: return False
                c[i] -= 1
                if c[i] == 0: del c[i]
        return True

class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        count = collections.Counter(hand)
        while count:
            m = min(count)
            for k in range(m, m+W):
                v = count[k]
                if not v: return False
                if v == 1:
                    del count[k]
                else:
                    count[k] = v - 1

        return True
            


class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        
        if len(hand) % W != 0:
            return False
     
        dic = defaultdict(int)
        for i in range(len(hand)):
            dic[ hand[i] ] += 1
        
        
        
        for i in range(0, len(hand), W):
            
            start = min(dic.keys())
            dic[start] -= 1
            if dic[start] == 0:
                del dic[start]
            for i in range(1, W):
                start += 1
                if start not in dic:
                    return False
                dic[start] -= 1
                if dic[start] == 0:
                    del dic[start]    
            
        return True

class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        cnt = collections.Counter(hand)
        while cnt:
            m = min(cnt)
            for i in range(m, m + W):
                if i not in cnt:
                    return False
                elif cnt[i] == 1:
                    del cnt[i]
                else:
                    cnt[i] -= 1
        return True

class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        c = Counter(hand)
        while c:
            i = min(c)
            for j in range(i, i + W):
                if not c[j]:
                    return False
                c[j] -= 1
                if not c[j]:
                    del c[j]
        return True

class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        # counter = collections.Counter(hand)
        d = collections.defaultdict(lambda:0)
        for h in hand:
            d[h]+=1
            
        # start = min(hand)
        
        while d:
            # print(d.keys())
            start = min(d.keys())
            for i in range(start, start+W):
                if not d[i]:
                    return False
                d[i]-=1
                if not d[i]:
                    del d[i]
        
        return True

from collections import Counter
class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        L = len(hand)
        if L % W != 0:
            return False
        count = Counter(hand)
        Nparts = L // W
        
        for i in range(Nparts):
            i_min = min(count.keys())
            for j in range(W):
                if (i_min + j) not in count:
                    return False
                count[i_min + j]  -= 1
                if count[i_min + j] == 0:
                    del count[i_min + j]
        return True 


class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        dp = defaultdict(list)
        for e in sorted(hand):
            dp[e].append(dp[e-1].pop()+1) if len(dp[e-1]) != 0 else dp[e].append(1)
            if dp[e] and dp[e][-1]==W: dp[e].pop()
        return all(len(e)==0 for e in list(dp.values()))
        # c = Counter(hand)
        # while c:
        #     x = min(c.keys())
        #     for i in range(x,x+W):
        #         if i not in c: return False
        #         c[i] -= 1
        #         if c[i] == 0: del c[i]
        # return True


class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
#         hand.sort()
        
#         mask = 0
        
#         i = 0
#         while i < len(hand):
#             lst = -1
#             k = 0
#             j = 0
#             for j in range(len(hand)):
#                 if mask & (1 << j) > 0:
#                     continue
#                 elif lst == -1 or lst == hand[j] - 1:
#                     mask = mask | (1 << j)
#                     lst = hand[j]
#                     k += 1
#                     i += 1
#                     if k == W:
#                         break 
            
#             if k != W:
#                 return False
                
#         return True

            counter = collections.Counter(hand)
            
            while counter:
                m = min(counter)
                for k in range(m, m+W):
                    
                    if not counter[k]:
                        return False
                    
                    counter[k] -= 1
                    
                    if counter[k] == 0:
                        del counter[k]
            return True


class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        n = len(hand)
        if n % W:
            return False
        
        C = Counter(hand)
        #print (C)
        for i in range(n//W):
            mn = min(C.keys())
            for j in range(mn, mn + W):
                if j not in C:
                    return False
                else:
                    C[j] -= 1
                    if C[j] == 0:
                        del C[j]
                    
        return True


from collections import Counter

class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        c = Counter(hand)
        while len(c) > 0:
            curr = min(c)
            v = c[curr]
            del(c[curr])
            for i in range(1,W):
                if curr + i not in c or c[curr + i] < v:
                    return False
                else:
                    c[curr + i] -= v
                    if c[curr + i] == 0:
                        del(c[curr+i])
        
        return True
            
            
                        
        


class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        count = collections.Counter(hand)
        while count:
            m = min(count)
            for k in range(m, m+W):
                v = count[k]
                if not v: return False
                if v == 1:
                    del count[k]
                else:
                    count[k] = v - 1

        return True

from collections import OrderedDict 

class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        numHash = {}
        for n in hand:
            if n not in numHash:
                numHash[n] = 1
            else:
                numHash[n] += 1
                
        while numHash:
            num = min(numHash)
            for n in range(W):
                nextNum = num + n
                
                if nextNum in numHash:
                    numHash[nextNum] -= 1
                    if numHash[nextNum] == 0:
                        del numHash[nextNum]
                else:
                    return False
        return True
        
        


from collections import OrderedDict
class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        count = collections.Counter(hand)
        while count:
            m = min(count)
            for k in range(m, m+W):
                v = count[k]
                if not v: return False
                if v == 1:
                    del count[k]
                else:
                    count[k] = v - 1

        return True
#         d = OrderedDict()
        
#         hand.sort()
        
#         # print(hand)
#         for val in hand:
#             if val in d:
#                 d[val] += 1
#             else:
#                 d.setdefault(val, 1)
            
#         i = 0
#         length = len(d)
#         items = list(d.items())
#         items = list(map(list, items))
#         while i <= length-W:
#             k, v = items[i]
#             if v == 0:
#                 i += 1
#                 continue
#             temp = W
#             j = i
#             prev = k
#             if j >= len(items):
#                 return False
#             while temp > 0:
#                 if items[j][0] != prev:
#                     return False
#                 else:
#                     items[j][1] -= 1
#                 j += 1
#                 prev = prev + 1
#                 temp -= 1
#                 if temp != 0 and j >= len(items):
#                     return False
        
#         for i in range(length-W, length):
#             k, v = items[i]
#             if v != 0:
#                 return False
#         return True


from collections import Counter
class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        if(len(hand) % W != 0):
            return False
        count = Counter(hand)
        while(count):
            min_v = min(count.keys())
            for i in range(min_v, min_v+W):
                if(count[i] == 0):
                    return False
                count[i]-=1
                if(count[i] == 0):
                    del count[i]
                    
        return True

from collections import Counter
class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        count = Counter(hand)
        
        while(count):
            m = min(count)
            for k in range(m, m + W):
                v = count[k]
                if not v:
                    return False
                if v == 1:
                    del count[k]
                    
                    
                else:
                    count[k] = v - 1
                    
                    
        return True

from collections import defaultdict
class Solution(object):
    def isNStraightHand(self, hand, W):
        dic = dict()
        for val in hand:
            dic[val] = dic.get(val, 0) + 1
        
        while dic:
            min_val = min(dic.keys())
            for i in range(min_val, min_val+W):
                v = dic.get(i, 0)
                if v == 0:
                    return False
                dic[i] -= 1
                if dic[i] == 0:
                    dic.pop(i)
                
        return True


class Solution:
    # WA
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        if W ** 2 != len(hand):
            return False
        hand.sort()
        for i in range(0, len(hand), W):
            for j in range(1, W):
                if hand[i + j] - hand[i + j - 1] != 1:
                    return False
        return True
                
class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        if len(hand) % W != 0:
            return False
        from collections import Counter
        ct = Counter(hand)
        hand = sorted(ct.items())
        # print(hand)
        i = 0
        while i < len(hand):
            if hand[i][1] == 0:
                i += 1
                continue
            hand[i] = (hand[i][0], hand[i][1] - 1)
            k = hand[i][0]
            # print(k)
            for j in range(1, W):
                k += 1
                if i + j < len(hand) and hand[i + j][0] == k:
                    # print(k)
                    hand[i + j] = (hand[i + j][0], hand[i + j][1] - 1)
                else:
                    return False
        return True
                    


class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        import collections
        count = collections.Counter(hand)
        while count:
            num = min(count.keys())
            val = count[num]
            for j in range(W):
                if count[num+j] < val:
                    return False
                elif count[num+j] == val:
                    del count[num+j]
                else:    
                    count[num+j] -= val
                
            
        return True


class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        # Time: O(n*n/w)
        # Space: O(n)
        
        count = collections.Counter(hand)
        while count:
            m = min(count)
            for j in range(m, m + W):
                if not count[j]:
                    return False
                if count[j] == 1:
                    del count[j]
                else:
                    count[j] -= 1
        return True

class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        if len(hand)%W!= 0:
            return False    
        freq = Counter(hand)
        
        while freq:
            m = min(freq)
            for i in range(m, m+W):
                v = freq[i]
                if not v: return False
                if v == 1:
                    del freq[i]
                else:
                    freq[i] -= 1
        return True
        


class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        if len(hand) % W != 0: return False
        count = collections.Counter(hand)
        while count:
            x = min(count)
            for k in range(x,x+W):
                v = count[k]
                if not v: return False
                if v == 1: del count[k]
                else: count[k] = v-1
        return True


class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        if len(hand) % W != 0:
            return False
        count = Counter(hand)
        for i in range(len(hand) // W):
            num, group_count = min(count.keys()), 0
            while group_count < W:
                count[num] -= 1
                if count[num] == 0:
                    del count[num]
                elif count[num] < 0:
                    return False
                group_count += 1
                num += 1
        return True

class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        if len(hand) % W != 0: return False
        counter = defaultdict(int)
        for elem in hand:
            counter[elem] += 1
        while len(counter) > 0:
            curr = min(counter.keys())
            counter[curr] -= 1
            if counter[curr] == 0:
                del counter[curr]
            for i in range(1,W):
                curr += 1
                if curr in counter:
                    counter[curr] -= 1
                    if counter[curr] == 0:
                        del counter[curr]
                else:
                    return False
        return True

class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        counter = collections.Counter(hand)
        
        while counter:
            starter = min(counter.keys())
            for i in range(W):
                if starter + i not in counter:
                    return False
                else:
                    counter[starter+i] -= 1
                    if counter[starter+i] == 0:
                        del counter[starter+i]
                        
        
        return True


class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        if len(hand) % W != 0:
            return False
        count = Counter(hand)
        for i in range(len(hand) // W):
            num = min(count.keys())
            for j in range(W):
                count[num+j] -= 1
                if count[num+j] == 0:
                    del count[num+j]
                elif count[num+j] < 0:
                    return False
        return True

class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        if len(hand)%W!= 0:
            return False    
        freq = Counter(hand)
        
        while freq:
            m = min(freq)
            for i in range(m, m+W):
                v = freq[i]
                if not v: return False
                if v == 1:
                    del freq[i]
                else:
                    freq[i] = v -1
        return True
        


class Solution:
    
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        if len(hand) % W != 0: return False
        
        hand = sorted(hand)
                
        failed = False
        while hand and not failed:
            group = [hand[0]]
            del hand[0]
                        
            idx = 0
            while len(group) < W and idx < len(hand):
                if group[-1] + 1 == hand[idx]: 
                    group.append(hand[idx])
                    del hand[idx]
                else:
                    idx += 1
                        
            if len(group) < W: failed = True
                    
        return not failed


class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        maps = Counter(hand)
        while maps:
            k = min(maps.keys())
            count = maps[k]
            for i in range(k, k + W): 
                if i not in maps or maps[i] < count:
                    return False
                maps[i] -= count
                if maps[i] == 0:
                    maps.pop(i)
                    
        return True


from collections import OrderedDict 

class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        numHash = {}
        
        for n in hand:
            if n not in numHash:
                numHash[n] = 1
            else:
                numHash[n] += 1
        numHash = OrderedDict(sorted(numHash.items()))
        while len(numHash) > 0:
            num = list(numHash.keys())[0]
            for n in range(W):
                nextNum = num + n
                
                if nextNum in numHash:
                    numHash[nextNum] -= 1
                    if numHash[nextNum] == 0:
                        del numHash[nextNum]
                else:
                    return False
        return True
        
        


class Solution(object):
    def isNStraightHand(self, hand, W):
        count = collections.Counter(hand)
        while count:
            m = min(count)
            for k in range(m, m+W):
                v = count[k]
                if not v: return False
                if v == 1:
                    del count[k]
                else:
                    count[k] = v - 1

        return True

class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        counter = collections.Counter(hand)
        
        while counter:
            num = min(counter)
            
            for _ in range(W):
                if num not in counter:
                    return False
                
                counter[num] -= 1
                if counter[num] == 0:
                    del counter[num]
                
                num += 1
                
        return True


from collections import Counter
class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        if len(hand) % W != 0:
            return False
        dic = Counter(hand)
        
        while dic:
            small = min(dic.keys())
            for i in range(small, small + W):
                if dic[i] ==0 :
                    return False
                dic[i] -= 1
                if dic[i] ==0:
                    del dic[i]
        return True
                    
        
            


class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        if len(hand) % W != 0:
            return False
        count = Counter(hand)
        # min_keys = sorted(count.keys())
        for i in range(len(hand) // W):
            # base = min_keys[0]
            base = min(count)
            for num in range(base, base+W):
                count[num] -= 1
                if count[num] == 0:
                    # min_keys.remove(num)
                    del count[num]
                elif count[num] < 0:
                    return False
        return True

class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        if len(hand)%W: return False
        counter = Counter(hand)
        keys = set(counter.keys())
        while counter:
            key = min(keys)
            while key in keys:
                for w in range(W):
                    if key+w not in counter:
                        return False
                    counter[key+w] -= 1
                    if counter[key+w] == 0:
                        del counter[key+w]
                        keys.remove(key+w)
        
        return True
    


class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        #if len(hand) != W**2:
        #    return False
        
        counted = {}
        for i in hand:
            if i not in counted:
                counted[i] = 0
            counted[i] += 1
        
        def containStrait(numbers, counted, W):
            #print(numbers, counted)
            if len(counted) == 0:
                return True
            if len(numbers) < W:
                return False
            
            if numbers[W - 1] - numbers[0] > W:
                return False
                #counted.pop(numbers[0])
                #numbers.remove(numbers[0])
                #return containStrait(numbers, counted, W, count)
            else:
                for i in reversed(range(W)):
                    counted[numbers[i]] -= 1
                    if counted[numbers[i]] == 0:
                        counted.pop(numbers[i])
                        numbers.remove(numbers[i])
                #count -= 1
            return containStrait(numbers, counted, W)
        
        numbers = sorted(counted.keys())
        return containStrait(numbers, counted, W)

import collections

class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        
        if W<1:
            return False
        
        if len(hand)%W != 0:
            return False
        
        counter = collections.Counter(hand)
        sorted(counter.items(), key=lambda i: i[0])
        
        dic = {}
        dic = collections.OrderedDict(sorted(dict(counter).items()))
        
        while dic:
        
            dic_list = list(dic.keys())

            base = dic_list[0]

            for i in range(W):
                if base+i not in dic:
                    return False
                dic[base+i] -= 1
                if dic[base+i]==0:
                    dic.pop(base+i, None)                
         
        return True

class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        
        counter = Counter(hand)
        heap_hands=[]
        groups=[]
        for k, v in counter.items():
            heapq.heappush(heap_hands,(k,v))
        
        while(heap_hands):
            count=0
            sub_group=[]
            remaining_elements=[]
            while(count<W):
                if not heap_hands:
                    return False
                popped_elem=heapq.heappop(heap_hands)
                if popped_elem[1]-1>0:
                    remaining_elements.append(popped_elem)
                if not sub_group:
                    sub_group.append(popped_elem[0])
                else:
                    if popped_elem[0]-1 == sub_group[-1]:
                        sub_group.append(popped_elem[0])
                    else:
                        return False
                count+=1

            groups+=sub_group
            for elem in remaining_elements:
                heapq.heappush(heap_hands,(elem[0],elem[1]-1))

        return True

class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        counted = {}
        for i in hand:
            if i not in counted:
                counted[i] = 0
            counted[i] += 1
        
        def containStrait(numbers, counted, W):
            if len(counted) == 0:
                return True
            if len(numbers) < W:
                return False
            
            if numbers[W - 1] - numbers[0] > W:
                return False
            else:
                for i in reversed(range(W)):
                    counted[numbers[i]] -= 1
                    if counted[numbers[i]] == 0:
                        counted.pop(numbers[i])
                        numbers.remove(numbers[i])
            return containStrait(numbers, counted, W)
        
        numbers = sorted(counted.keys())
        return containStrait(numbers, counted, W)

from collections import Counter

class Solution:
    '''def isNStraightHand(self, hand: List[int], W: int) -> bool:
        if len(hand)<W or len(hand)%W!=0:
            return False
        count = Counter(hand)

        while count:
            sublist = []
            item = min(count)
            sublist.append(item)
            if count[item]==1:
                del count[item]
            else:
                count[item]-=1
            while len(sublist)<W:
                item+=1
                if item not in count:
                    return False
                sublist.append(item+1)
                if count[item]==1:
                    del count[item]
                else:
                    count[item]-=1
        return True'''
        
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        # no need to store the subist themselves 
        if len(hand)<W or len(hand)%W!=0:
            return False
        count = Counter(hand)

        while count:
            item = min(count)
            if count[item]==1:
                del count[item]
            else:
                count[item]-=1
            i= 1
            while i<W:
                item+=1
                i+=1
                if item not in count:
                    return False
                if count[item]==1:
                    del count[item]
                else:
                    count[item]-=1
        return True

class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        count = collections.Counter(hand)
        while count:
            m = min(count)
            for i in range(m, m+W):
                if not count[i]:
                    return False
                if count[i] == 1:
                    del(count[i])
                else:
                    count[i] -= 1
        return True


class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        #if len(hand) != W**2:
        #    return False
        
        counted = {}
        for i in hand:
            if i not in counted:
                counted[i] = 0
            counted[i] += 1
        
        def containStrait(numbers, counted, W):
            #print(numbers, counted)
            if len(counted) == 0:
                return True
            if len(numbers) < W:
                return False
            
            if numbers[W - 1] - numbers[0] > W:
                counted.pop(numbers[0])
                numbers.remove(numbers[0])
                #return containStrait(numbers, counted, W, count)
            else:
                for i in reversed(range(W)):
                    counted[numbers[i]] -= 1
                    if counted[numbers[i]] == 0:
                        counted.pop(numbers[i])
                        numbers.remove(numbers[i])
                #count -= 1
            return containStrait(numbers, counted, W)
        
        numbers = sorted(counted.keys())
        return containStrait(numbers, counted, W)

class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        hand.sort()
        
        if len(hand)%W!=0:
            return False
        
        while hand:
            z = min(hand)
            for t in range(z,z+W):
                try:
                    hand.remove(t)
                except:
                    return False
        
        return True


class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        #if len(hand) != W**2:
        #    return False
        
        counted = {}
        for i in hand:
            if i not in counted:
                counted[i] = 0
            counted[i] += 1
        
        def containStrait(numbers, counted, W):
            #print(numbers, counted)
            if len(counted) == 0:
                return True
            if len(numbers) < W:
                return False
            
            if numbers[W - 1] - numbers[0] > W:
                counted.pop(numbers[0])
                numbers.remove(numbers[0])
                #return containStrait(numbers, counted, W, count)
            else:
                min_count = sys.maxsize
                for i in reversed(range(W)):
                    if counted[numbers[i]] < min_count:
                        min_count = counted[numbers[i]]
                    
                for i in reversed(range(W)):
                    counted[numbers[i]] -= min_count
                    if counted[numbers[i]] == 0:
                        counted.pop(numbers[i])
                        numbers.remove(numbers[i])
                #count -= 1
            return containStrait(numbers, counted, W)
        
        numbers = sorted(counted.keys())
        return containStrait(numbers, counted, W)

class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        dp = defaultdict(list)
        
        for e in sorted(hand):
            dp[e].append(dp[e-1].pop()+1) if len(dp[e-1]) != 0 else dp[e].append(1)
            if dp[e] and dp[e][-1]==W: dp[e].pop()
                
            
                
        return all(len(e)==0 for e in list(dp.values()))
        # c = Counter(hand)
        # while c:
        #     x = min(c.keys())
        #     for i in range(x,x+W):
        #         if i not in c: return False
        #         c[i] -= 1
        #         if c[i] == 0: del c[i]
        # return True



from collections import Counter
class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        if len(hand)%W != 0:
            return False
        count_dict = Counter(hand)
        while count_dict:
            m = min(count_dict)
            for i in range(m,m+W):
                if i not in count_dict:
                    return False
                elif count_dict[i] == 1:
                    del(count_dict[i])
                else:
                    count_dict[i]-=1
        return True
                
                    

                    


class Solution:
    def isNStraightHand(self, nums: List[int], W: int) -> bool:
        n = len(nums)

        if n % W != 0:
            return False

        nums.sort()

        dic = OrderedDict()

        for num in nums:
            dic[num] = dic.get(num, 0) + 1

        while dic:
            m = min(dic)
            for i in range(m, m+W):
                val = dic.get(i)

                if not val:
                    return False
                if val == 1:
                    del dic[i]
                else:
                    dic[i] -= 1
        return True



import collections
class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        handCounter = Counter()
        for number in hand:
            handCounter[number] += 1
        while len(handCounter) != 0:
            m = min(handCounter.keys())
            for i in range(m, m+W):
                if i not in handCounter:
                    return False
                handCounter[i] -= 1
                if handCounter[i] == 0:
                    del handCounter[i]
        
        return True

class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        if len(hand) % W != 0:
            return False

        cardCount = {}

        for card in hand:
            if not card in cardCount:
                cardCount[card] = 0
            cardCount[card] += 1

        k = len(hand) // W

        for i in range(k):
            start = min(cardCount.keys())
            
            for j in range(W):
                if not start + j in cardCount:
                    return False

            for j in range(W):
                cardCount[start + j] -= 1
                if cardCount[start + j] == 0:
                    cardCount.pop(start + j)

        return True



class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        count = collections.Counter(hand)
        while count:
            m = min(count)
            for k in range(m, m+W):
                v = count[k]
                if not v: return False    # if v is zero 
                if v == 1:
                    del count[k]
                else:
                    count[k] = v - 1

        return True


from collections import Counter

class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        
        counter = Counter(hand)
        # print (counter)
        
        while counter:
            
            key = min(counter)
            for x in range(key, key + W):
                if counter[x] < 1:
                    return False
                counter[x] -= 1
                if counter[x] == 0:
                    del counter[x]
        
        return True

class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        hand.sort()
        
        def helper(hand):
            # print(hand)
            if not hand: return
            if len(hand) % W != 0: 
                self.ans = False
                return
            n = len(hand)
            i, k = 0, 0
            prev = hand[0]-1
            new_hand = []
            while i < n and k < W:
                if hand[i] == prev:
                    new_hand.append(hand[i])
                else:
                    if hand[i] != prev + 1:
                        self.ans = False
                        return
                    else:
                        prev += 1
                        k += 1
                i += 1
            
            new_hand += hand[i:]
            if not new_hand:
                self.ans = True
                return
            return helper(new_hand)
    
        helper(hand)
        return self.ans

class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        count = Counter(hand)
        result = []
        while count:
            m = min(count)
            straights = []
            for i in range(m, m + W):
                if i in count:
                    straights.append(i)
                    count[i] -= 1
                    if count[i] == 0:
                        del count[i]
                else:
                    return False
            result.append(straights)
        print(result)
        return True


class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        if len(hand) % W != 0:
            return False
        counter = collections.Counter(hand)
        while counter:
            smallest = min(counter)
            for j in range(smallest, smallest+W):
                if j not in counter:
                    return False
                counter[j] -= 1
                if counter[j] == 0:
                    del counter[j]
        return True

class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        count = collections.Counter(hand)
        dic = collections.OrderedDict(sorted(count.items()))
        while dic:
            m = next(iter(dic))
            #print(m)
            for k in range(m, m+W):
                v = dic.get(k)
                print(v,k)
                if not v: 
                    return False
                if v == 1:
                    del dic[k]
                else:
                    dic[k] = v - 1

        return True

class Solution:
    def isNStraightHand(self, nums: List[int], W: int) -> bool:
        n = len(nums)

        if n % W != 0:
            return False

        nums.sort()

        dic = OrderedDict()

        for num in nums:
            dic[num] = dic.get(num, 0) + 1

        while len(list(dic.keys())) > 0:
            m = min(dic)
            for i in range(m, m+W):
                val = dic.get(i)

                if not val:
                    return False
                if val == 1:
                    del dic[i]
                else:
                    dic[i] -= 1
        return True



class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        counter = collections.Counter(hand)
        s = set(hand)
        
        while s:
            minv = min(s)
            for i in range(minv, minv + W):
                if i not in counter or counter[i] == 0:
                    return False
                counter[i] -= 1
                if counter[i] == 0:
                    s.remove(i)
        
        return True

from collections import Counter
class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        c = Counter(hand)
        while c:
            j = min(c)
            for i in range(j,j+W):
                if not c[i]:
                    return False
                if c[i] == 1:
                    del c[i]
                else:
                    c[i] -= 1
        return True


class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        counter = collections.Counter(hand)
        s = set(hand)
        
        while s:
            minv = min(s)
            for i in range(minv, minv + W):
                if i not in counter:
                    return False
                counter[i] -= 1
                if counter[i] == 0:
                    del counter[i]
                    s.remove(i)
        
        return True

class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        if len(hand) % W != 0:
            return False
        # digits = collections.defaultdict(int)
        # for d in hand:
            # digits[d] += 1
        count = collections.Counter(hand)
        while count:
            m = min(count)
            # k, v = sorted(digits.items())[0]
            for k in range(m, m+W):
                v = count[k]
                if not v:
                    return False
                if v == 1:
                    del count[k]
                else:
                    count[k] -= 1
        return True
            
            


class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        count = collections.Counter(hand)
        while count:
            m = min(count)
            for k in range(m, m + W):
                if not count[k]:
                    return False
                if count[k] == 1:
                    del count[k]
                else:
                    count[k] -= 1
        return True

class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        
        if len(hand) % W != 0:
            return False
        
        counter = Counter(hand)
        
        while counter:
            start = min(counter)
            
            for n in range(start, start + W):
                if n in counter:
                    counter[n] -= 1
                    if counter[n] == 0:
                        del counter[n]
                else:
                    return False
        return True


class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        n = len(hand)
        if n % W != 0: 
            return False
        
        hand = sorted(hand)
        counts = collections.Counter(hand) # key: card, val: freq
        print(counts)
        # tree map: ordered hashmap
        while sum(counts.values()) > 0:
            start_card = min(counts)
            print(start_card)
            
            for card in range(start_card, start_card + W):
                # check each group in one for-loop
                if card not in counts:
                    return False
                counts[card] -= 1
                if counts[card] == 0:
                    del counts[card]
        
            # counts[start_card] -= 1
            # if counts[start_card] == 0:
            #     del counts[start_card]
                
        return True


class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        hand = collections.Counter(hand)
        while True:
            if len(hand) == 0:
                return True
            m = min(hand)
            for c in range(m, m + W):
                if c not in hand:
                    return False
                if hand[c] == 1:
                    del hand[c]
                else:
                    hand[c] -= 1


class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        dic = collections.OrderedDict(sorted(collections.Counter(hand).items()))
        while dic:
            m = next(iter(dic))
            #print(m)
            for k in range(m, m+W):
                v = dic.get(k)
                #print(v,k)
                if not v: 
                    return False
                if v == 1:
                    del dic[k]
                else:
                    dic[k] = v - 1

        return True

class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        n = len(hand)
        if n % W != 0: return False
        count = collections.Counter(hand)
        while n > 0:
            a = min(count)
            for i in range(W):
                if count[a + i] <= 0:
                    return False
                count[a + i] -= 1
                if count[a + i] == 0:
                    del count[a + i]
            n -= W
        return True

from collections import Counter
class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        '''
        O(n log n): sort the hand, every time we see dont have a consecutive value
                 or hit length W, we start a new group
                 
        '''
        counter = Counter(hand)
        count = W
        while counter:
            if count == W:
                count = 0
                val = min(counter)
            else:
                val += 1
                if not counter[val]:
                    return False                    
            counter[val] -= 1
            if not counter[val]:
                del counter[val]
            count += 1
        return count == W


class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        if not hand or len(hand)%W != 0:
            return False
        hand_dict = self.get_hand_dict(hand)
        return self.is_n_straigh_hand(hand_dict, W)
        
    def is_n_straigh_hand(self, hand_dict, W):
        while hand_dict:
            start_hand = min(hand_dict)
            count = hand_dict[start_hand]
            for i in range(start_hand, W + start_hand):
                if i not in hand_dict:
                    return False
                else:
                    hand_dict[i] -= count
                    if hand_dict[i] == 0:
                        del hand_dict[i]
                    elif hand_dict[i] < 0:
                        return False
        return True
    
    def get_hand_dict(self, hand):
        hand_dict = {}
        for h in hand:
            hand_dict[h] = hand_dict.get(h, 0)
            hand_dict[h] += 1
        return hand_dict
    
#         if not hand or len(hand)%W != 0:
#             return False
#         result = [[] * W for _ in range(len(hand)//W)]
#         hand_dict = self.get_dict(hand)
#         return self.is_n_straight_hand(hand_dict, W, result)
    
#     def is_n_straight_hand(self, hand_dict, W, result):
#         while hand_dict:
#             min_hand = min(hand_dict)
#             count = hand_dict[min_hand]
#             for i in range(min_hand, min_hand + W):
#                 if i not in hand_dict:
#                     return False
#                 hand_dict[i] -= count
#                 if hand_dict[i] == 0:
#                     del hand_dict[i]
#                 elif hand_dict[i] < 0:
#                     return False
#         return True
                    
            
    
#     def get_dict(self, hand):
#         hand_dict = {}
#         for i in hand:
#             hand_dict[i] = hand_dict.get(i, 0) + 1
#         return hand_dict


class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        count = collections.Counter(hand)
        while count:
            mins = min(count)
            for i in range(mins, mins + W):
                if not count[i]:
                    return False
                if count[i] == 1:
                    del count[i]
                else:
                    count[i] -= 1
        return True
        # heapq.heapify(hand)
        # while hand:
        #     mins = hand[0]
        #     #print(hand)
        #     for i in range(mins, mins + W):
        #         #print(i)
        #         if i in hand:
        #             hand.remove(i)
        #             heapq.heapify(hand)
        #         else:
        #             return False
        # return True


class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        N = len(hand)
        
        if N % W != 0:
            return False
        
        
        counts = collections.Counter(hand)
        
        while counts:
            card = min(counts.keys())
            

            for _ in range(W):
                if card not in counts:
                    return False

                counts[card] -= 1
                if counts[card] == 0:
                    del counts[card]

                card += 1
        
        
        return True
    


from collections import Counter
class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        cs = Counter(hand)
        
        while cs:
            card = next(card for card in cs if card-1 not in cs)-1
            
            l = -1
            while (l:=l+1) < W and cs[(card:=card+1)]:
                cs[card] -= 1
                if cs[card] == 0: del cs[card]
            
            if l != W:
                return False
        
        return True  
        


class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        count = collections.Counter(hand)
        
        while count:
            minCount = min(count)
            
            for i in range(minCount, minCount+W):
                if not count[i]: # if i not in count:
                    return False
                if count[i] == 1:
                    del count[i]
                else:
                    count[i] -= 1
        return True

class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        
        if len(hand)%W:
            return False
        
        counter = dict()
        for h in hand:
            temp = counter.get(h, 0)
            temp+=1
            counter[h] = temp
        
        
        while counter:
            start = min(counter.keys())
            for k in range(start, start+W):
                v = counter.get(k)
                
                if not v:
                    return False
                if v==1:
                    del counter[k]
                else:
                    counter[k] = v-1
        return True
                    


# 时间复杂度：O(N * (N/W))O(N∗(N/W))，其中 NN 是 hand 的长度，(N / W)(N/W) 是 min(count) 的复杂度。
# 在 Java 中使用 TreeMap 可以将 (N / W)(N/W) 降低到 \\log NlogN。

# 空间复杂度：O(N)O(N)。
class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        count = collections.Counter(hand)
        while count:
            m = min(count)
            for k in range(m, m+W):
                v = count[k]
                if not v: return False
                if v == 1:
                    del count[k]
                else:
                    count[k] = v - 1

        return True



class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        count = Counter(hand)
        result = []
        while count:
            m = min(count)
            straights = []
            for i in range(m, m + W):
                if i in count:
                    straights.append(i)
                    count[i] -= 1
                    if count[i] == 0:
                        del count[i]
                else:
                    return False
                
        return True


class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        if not hand or len(hand)%W != 0:
            return False
        hand_dict = self.get_hand_dict(hand)
        return self.is_n_straigh_hand(hand_dict, W)
        
    def is_n_straigh_hand(self, hand_dict, W):
        while hand_dict:
            start_hand = min(hand_dict)
            for i in range(start_hand, W + start_hand):
                if i not in hand_dict:
                    return False
                else:
                    hand_dict[i] -= 1
                    if hand_dict[i] == 0:
                        del hand_dict[i]
        return True
    
    def get_hand_dict(self, hand):
        hand_dict = {}
        for h in hand:
            hand_dict[h] = hand_dict.get(h, 0)
            hand_dict[h] += 1
        return hand_dict
    
#         if not hand or len(hand)%W != 0:
#             return False
#         result = [[] * W for _ in range(len(hand)//W)]
#         hand_dict = self.get_dict(hand)
#         return self.is_n_straight_hand(hand_dict, W, result)
    
#     def is_n_straight_hand(self, hand_dict, W, result):
#         while hand_dict:
#             min_hand = min(hand_dict)
#             count = hand_dict[min_hand]
#             for i in range(min_hand, min_hand + W):
#                 if i not in hand_dict:
#                     return False
#                 hand_dict[i] -= count
#                 if hand_dict[i] == 0:
#                     del hand_dict[i]
#                 elif hand_dict[i] < 0:
#                     return False
#         return True
                    
            
    
#     def get_dict(self, hand):
#         hand_dict = {}
#         for i in hand:
#             hand_dict[i] = hand_dict.get(i, 0) + 1
#         return hand_dict


class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        n = len(hand)
        if n % W != 0: 
            return False
        
        counts = collections.Counter(hand) # key: card, val: freq

        while sum(counts.values()) > 0:
            start_card = min(counts)
            print(start_card)
            
            for card in range(start_card, start_card + W):
                # check each group in one for-loop
                if card not in counts:
                    return False
                counts[card] -= 1
                if counts[card] == 0:
                    del counts[card]
                
        return True


class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        n = len(hand)
        if n % W != 0: 
            return False
        
        counts = collections.Counter(hand) # key: card, val: freq

        # tree map: ordered hashmap
        while sum(counts.values()) > 0:
            start_card = min(counts)
            print(start_card)
            
            for card in range(start_card, start_card + W):
                # check each group in one for-loop
                if card not in counts:
                    return False
                counts[card] -= 1
                if counts[card] == 0:
                    del counts[card]
                
        return True


class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        count = collections.Counter(hand)
        while count:
            m = min(count)
            for k in range(m, m + W):
                v = count[k]
                if not v:
                    return False
                if v == 1:
                    del count[k]
                else:
                    count[k] = v - 1
        return True

class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        n = len(hand)
        if n % W != 0:
            return False
        c = collections.Counter(hand)
        while c:
            k = min(c)
            v = c[k]
            del c[k]
            for i in range(1,W):
                if c[k+i] < v:
                    return False
                else:
                    c[k+i] -= v
                    if c[k+i] == 0:
                        del c[k+i]
        return True

class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        card_dict = dict()
        #min_heap = heapq()
        for card in hand:
            if card in card_dict:
                card_dict[card] = card_dict[card] + 1
                
            else:
                card_dict[card] = 1
                #min_heap.push(card)
                
        while(len(card_dict) > 0):
            min_ele = min(card_dict.keys())
            for i in range(W):
                if not min_ele in card_dict:
                    return False
                
                elif card_dict[min_ele] > 1:
                    card_dict[min_ele] = card_dict[min_ele] - 1
                    
                else:
                    del card_dict[min_ele]
                     
                min_ele = min_ele + 1
                    
        return True
        
        


class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        count = Counter(hand)
        result = []
        while count:
            m = min(count)
            straights = []
            for i in range(m, m + W):
                if i in count:
                    #straights.append(i)
                    count[i] -= 1
                    if count[i] == 0:
                        del count[i]
                else:
                    return False
            #result.append(straights)
        #print(result)
        return True


class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        if len(hand) % W != 0:
            return False
        hand.sort()
        flag = 0
        while len(hand) > 0 and flag == 0:
            temp = []
            start = hand[0]
            temp.append(start)
            for i in range(1,W):
                if start+i in hand:
                    temp.append(start+i)
                else:
                    flag = 1
                    break     
            for x in temp:
                hand.remove(x)
            
        if flag == 0:
            return True
        else:
            return False

class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        count = collections.Counter(hand)
        while count:
            mins = min(count)
            for i in range(mins, mins + W):
                if not count[i]:
                    return False
                if count[i] == 1:
                    del count[i]
                else:
                    count[i] -= 1
        return True
        heapq.heapify(hand)


class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        if len(hand) % W != 0:
            return False
        count = Counter(hand)
        result = []
        while count:
            m = min(count)
            straights = []
            for i in range(m, m + W):
                if i in count:
                    #straights.append(i)
                    count[i] -= 1
                    if count[i] == 0:
                        del count[i]
                else:
                    return False
            #result.append(straights)
        #print(result)
        return True


class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        if len(hand) % W != 0:
            return False
        hand.sort()
        flag = 0
        while len(hand) > 0 and flag == 0:
            temp = []
            start = hand[0]
            temp.append(start)
            print(start)
            for i in range(1,W):
                if start+i in hand:
                    temp.append(start+i)
                else:
                    flag = 1
                    break     
            for x in temp:
                hand.remove(x)
            
        if flag == 0:
            return True
        else:
            return False

class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        
        count = Counter(hand)
        
        while (count):
            init = min(count.keys())
            if count[init] ==1: 
                del count[init]
            else:
                count[init]= count[init]-1
            for i in range(1, W):

                v = count[init+1]
                if (init+1) in count.keys():
                    
                    if v==1: 
                        del count[init+1]
                    else:
                        count[init+1]= v-1
                else:
                    return False
                init = init+1
        return True

class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        
        if len(hand) % W != 0:
            
            return False
         
        freq_dict = collections.Counter(hand)
        
        while freq_dict:
            
            min_num = min(freq_dict)
            
            for i in range(min_num, min_num + W):
                
                freq = freq_dict[i]
                       
                if freq == 0:
                    
                    return False
                
                elif freq == 1:
                    
                    del freq_dict[i]
                
                else:
                    
                    freq_dict[i] -= 1
                    
        return True

class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        hand.sort()
        dic = collections.Counter(hand)
        while dic:
            m = next(iter(dic))
            #print(m)
            for k in range(m, m+W):
                v = dic.get(k)
                #print(v,k)
                if not v: 
                    return False
                if v == 1:
                    del dic[k]
                else:
                    dic[k] = v - 1

        return True

class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        count = collections.Counter(hand)
        while count:
            m = min(count)
            for k in range(m, m+W):
                v = count[k]
                if not v: return False
                if v == 1:
                    del count[k]
                else:
                    count[k] = v - 1

        return True


from collections import Counter
class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        '''
        O(n)
        '''
        counter = Counter(hand)
        count = W
        while counter:
            if count == W:
                count = 0
                val = min(counter)
            else:
                val += 1
                if not counter[val]:
                    return False                    
            counter[val] -= 1
            if not counter[val]:
                del counter[val]
            count += 1
        return count == W


class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        if len(hand) % W != 0:
            return False
        counter = Counter(hand)
        for i in range(len(hand) // W):
            minimum = min(counter.keys())
            for number in range(minimum, minimum + W):
                if number not in counter:
                    return False
                counter[number] -= 1
                if counter[number] == 0:
                    del counter[number]
        return True
            
            
        
        


class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        
        if len(hand)%W!=0:
            return False
        
        hand.sort()
        
        last=-1
        j=0
        changed=False
        while hand:
            if hand[0]==last+1 or last==-1:
                changed=False
                last=hand.pop(0)
                j+=1
                if j%W==0:
                    last=-1
            elif not changed:
                for i in range(1, len(hand)):
                    if hand[i]<=last+1:
                        hand[i],hand[0]=hand[0],hand[i]
                    else:
                        break
                
                changed=True
            else:
                return False
                
        return True


from collections import Counter
class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        count = Counter(hand)
        while count:
            m = min(count)
            for k in range(m, m+W):
                v  = count[k]
                if not v:
                    return False
                if v == 1:
                    del count[k]
                else:
                    count[k] -= 1
        return True


class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        counter = collections.Counter(hand)
        
        while counter:
            num = min(counter)
            
            for _ in range(W):
                if num not in counter:
                    return False
                
                counter[num] -= 1
                
                if counter[num] == 0:
                    del counter[num]
                    
                num += 1
                    
        return True

from collections import Counter
class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        if len(hand) % W != 0:
            return False
        
        parts = len(hand) / W
        
        cnt = Counter(hand)
        cnt = sorted(cnt.items())
        #print(cnt)
        heapq.heapify(cnt)
        #print(cnt)

        while cnt:
            #print(cnt)
            hand = []
            while len(hand) != W:
                if not cnt:
                    return False

                (card, count) = heapq.heappop(cnt)
                if hand:
                    (last_card, last_count) = hand[-1]
                    if last_card != card - 1:
                        return False
                hand.append((card, count))

            #print(hand)
            for (card, count) in hand:
                count -= 1
                if count:
                    heapq.heappush(cnt, (card, count))

        return True

import heapq

class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        
        l = len(hand)
        if l == 0 or l % W != 0:
            return False
        
        counter = collections.Counter(hand)
        
        
        
        pos = 0
        while pos < l:
  
            currMin = min(counter.keys())
            counter[currMin] -= 1
            pos += 1
            if counter[currMin] == 0:
                del counter[currMin]
        
            for i in range(W-1):
                nextDraw = currMin + i + 1
                if nextDraw in counter and counter[nextDraw] > 0:
                    counter[nextDraw] -= 1
                    pos += 1
                    if counter[nextDraw] == 0:
                        del counter[nextDraw]
                else:
                    return False
                
        return True


class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        l=len(hand)
        if l%W!=0:
            return False
        d={}
        for i in range(l):
            if hand[i] not in d:
                d[hand[i]]=1
            else:
                d[hand[i]]+=1
        while d:
            num=min(d)
            j=1
            while num+1 in d and j!=W:
                j+=1
                num=num+1
            if j==W:
                num=min(d)
                for k in range(W):
                    if d[num]==1:
                        del d[num]
                    else:
                        d[num]-=1
                    num+=1
            else:
                return False
        return True


class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        count = collections.Counter(hand)
        while count:
            mins = min(count)
            for i in range(mins, mins + W):
                if not count[i]:
                    return False
                if count[i] == 1:
                    del count[i]
                else:
                    count[i] -= 1
        return True

class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        l=len(hand)
        if l%W!=0:
            return False
        d=collections.Counter(hand)
        while d:
            num=min(d)
            j=1
            while num+1 in d and j!=W:
                j+=1
                num=num+1
            if j==W:
                num=min(d)
                for k in range(W):
                    if d[num]==1:
                        del d[num]
                    else:
                        d[num]-=1
                    num+=1
            else:
                return False
        return True


class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        count = collections.Counter(hand)
        while count:
            m = min(count)
            for k in range(m, m+W):
                v = count[k]
                if not v:
                    return False
                if v == 1:
                    del count[k]
                else:
                    count[k] = v - 1

        return True

class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        if len(hand) % W != 0:
            return False
        
        hand = sorted(hand)
        # print(hand)
        
        for split in range(len(hand) // W):
            min_val = min(hand)
            hand.remove(min_val)
            for i in range(1, W):
                if min_val + 1 not in hand:
                    return False
                else:
                    min_val += 1
                    hand.remove(min_val)
        
        return True

class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        
        # input checking
        if len(hand) % W != 0 or not W:
            return False
        
        avail = collections.Counter(hand)
        while avail:
            curr = min(avail)
            for i in range(W):
                if avail[curr+i]:
                    avail[curr+i] -= 1
                    if not avail[curr+i]:
                        del avail[curr+i]
                else:
                    return False
        return True

class Solution:
    def isNStraightHand(self, hand, W):
        if len(hand) % W != 0:
            return False

        hand = sorted(hand)
        cnt = {}

        for card in hand:
            if card not in cnt:
                cnt[card] = 0
            cnt[card] += 1

        cur_len = 0
        last_val = -1
        num_sub_hands = 0

        unique_vals = sorted(set(hand))
        flag = True

        loops = 0

        while len(cnt) and flag and num_sub_hands < len(hand) // W:
            flag = False
            # pass by value
            tmp = sorted(set(unique_vals))

            for element in tmp:
                loops += 1
                if last_val == -1 or element == last_val + 1:
                    last_val = element
                    cnt[element] -= 1
                    cur_len += 1
                    flag = True
                if cnt[element] == 0:
                    del cnt[element]
                    unique_vals.remove(element)
                if cur_len == W:
                    last_val = -1
                    cur_len = 0
                    num_sub_hands += 1
                    break

        return len(cnt) == 0 and num_sub_hands == len(hand) // W

class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        
        dic = collections.Counter(hand)
        
        print((dic, min(dic), dic[10]))
        
        while dic:
            m = min(dic)
            
            for num in range(m,m+W):
                
                if dic[num] == 0:
                    return False
                
                if dic[num] == 1:
                    del dic[num]
                else:
                    dic[num] = dic[num] - 1
                
        return True
        


class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        hand = sorted(hand)
        forward = list(range(1,len(hand)))
        forward.append(None)
        backward = [None]
        backward.extend(list(range(0,len(hand)-1)))
        
        ptr = 0
        while ptr is not None:
            firstSkipped = None
            for i in range(W):
                if ptr is None:
                    return False
                currHand = hand[ptr]
                prev = backward[ptr]
                forw = forward[ptr]
                if prev is not None:
                    forward[prev] = forw
                    
                if forw is not None:
                    backward[forw] = prev
                forward[ptr] = backward[ptr] = None
                ptr = forw
                
                while ptr is not None and hand[ptr] == currHand:
                    if firstSkipped is None:
                        firstSkipped = ptr
                    ptr = forward[ptr]
                
                if ptr is not None and i != W-1 and hand[ptr] - 1!= currHand:
                    return False
                    
            if firstSkipped is not None:
                ptr = firstSkipped
        return True

class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        if(len(hand)%W != 0):
            return False
        
        data = collections.Counter(hand)
        while(data):
            m = min(data)
            for k in range(m, m+W):
                v = data[k]
                if(not v):
                    return False
                if(v == 1):
                    del data[k]
                else:
                    data[k] -= 1
        return True


class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        l = len(hand)
        if l % W != 0:
            return False
        cards = Counter(hand)
        keys = sorted(list(cards.keys()))
        start = keys[0]
        start_idx = 0
        for _ in range(l//W):
            cards[start] -= 1
            for i in range(start+1, start+W):
                if i not in keys or cards[i] == 0:
                    return False
                else:
                    cards[i] -= 1
            while cards[start] == 0 and start_idx < len(keys)-1:
                start_idx += 1
                start = keys[start_idx]
        return True

class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:

        counts = defaultdict(int)
        for number in hand:
            counts[number] += 1

        ordered_numbers = sorted(counts.keys())
        while counts:
            group = []
            for number in ordered_numbers:

                if number not in counts:
                    continue

                if counts[number] > 0:
                    if group:
                        if group[-1] != number - 1:
                            return False
                    group.append(number)
                    counts[number] -= 1
                else:
                    del counts[number]
                if len(group) == W:
                    break
            if group and len(group) != W:
                return False
        
        return True

class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        d=collections.defaultdict(int)
        for i in hand:
            d[i]+=1
        while(d):
            l=list(d)
            heapq.heapify(l)
            prev=None
            for i in range(W):
                if len(l)==0:
                    return False
                ele=heapq.heappop(l)
                if prev is not None:
                    if ele-prev>1:
                        return False
                prev=ele
                if d[ele]==1:
                    del d[ele]
                else:
                    d[ele]-=1
        return True
        
            
            


class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        hand = sorted(hand)
        indices = {}
        for index in reversed(list(range(len(hand)))):
            num = hand[index]
            if num not in indices:
                indices[num] = [index]
            else:
                indices[num].append(index)
        while len(indices) != 0:
            first = None
            for num in hand:
                if num in indices:
                    first = num
                    break
            for i in range(W):
                num = first + i
                if num in indices:
                    indices[num].pop()
                    if len(indices[num]) == 0: del indices[num]
                else:
                    return False
        return True
                    
                


class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        if not hand or not W:
            return False
        _map = defaultdict(list)
        for i in range(len(hand)):
            _map[hand[i]] += [i]
            
        while _map:
            hand = [k for k, _ in list(_map.items())]
            top = min(hand)
            _map[top].pop()
            if not _map[top]:
                del _map[top]
            i = 1
            while hand and i < W:
                top += 1
                if top not in _map:
                    return False
                _map[top].pop()
                if not _map[top]:
                    del _map[top]
                i += 1
            if i < W:
                return False
        return True


class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        l = len(hand)
        if l%W!=0:
            return False
        if W == 1:
            return True
        ct = Counter(hand)
        lst = sorted(list(ct.keys()))
        for l in lst:
            if l-1 not in lst and l+1 not in lst:
                return False
        while lst:
            # print(lst)
            begin = lst[0]
            ct[begin]-=1
            if ct[begin]==0:
                lst.pop(0)
            for i in range(1, W):
                if begin+i not in ct:
                    return False
                else:
                    ct[begin+i]-=1
                    if ct[begin+i]==0:
                        lst.remove(begin+i)
        return True


class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:

        if len(hand) % W!=0:
            return False

        if len(hand)==0:
            return True

        hand = sorted(hand)

        '''
        hand_dict = {}

        for h in hand:
            if h in hand_dict:
                hand_dict[h]+=1
            else:
                hand_dict[h]=1

        print(hand_dict)
        '''

        
    
        seed = hand[0]

        for i in range(1,W):

            #print(seed, seed+i)
            
            if seed+i not in hand:
                return False

        for i in range(0,W):
            hand.remove(seed+i)
            
        #print(hand)

        return self.isNStraightHand(hand, W)



from collections import OrderedDict

class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        if W==1:
            return True
        if len(hand)%W:
            return False
        hand.sort()
        od=OrderedDict()
        for h in hand:
            if h in od:
                od[h]+=1
            else:
                od[h]=1
        k=list(od.keys())[0]
        n=list(od.values())[0]
        while True:
            for i in range(W):
                if k+i in od and od[k+i]>=n:
                    od[k+i]-=n
                    if od[k+i]==0:
                        del od[k+i]
                else:
                    return False
            if len(od)==0:
                break
            k=list(od.keys())[0]
            n=list(od.values())[0]
        return True

class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        if len(hand) % W != 0:
            return False
        
        # we count the frequencies of each card and put it in an ordered dict
        counter = collections.Counter(hand)
        d = collections.OrderedDict(sorted(counter.items()))
        count = 0 # track the number of keys whose value is down to 0
        while count < len(d): 
            group = []
            # go through the ordered dict and put consecutive cards in a group
            # the loop breaks once the size of the group reaches W
            for card in d.keys():
                if d[card] == 0:
                    continue
                if not group or (len(group) < W and group[-1] + 1 == card):
                    group.append(card)
                    d[card] -= 1
                    if d[card] == 0:
                        count += 1
                if len(group) == W:
                    break
            else:
                return False
            
        return True

class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        
        if len(hand)% W !=0:
            return False
        
        while(hand!=[]):
            minele = min(hand)
            for i in range(0, W):
                try:
                    #print(minele+i)
                    hand.remove(minele+i)
                except:
                    return False
        return True
            
       


class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        if len(hand)%W!=0:
            return False
        else:
            while hand!=[]:
                f = min(hand)
                for i in range(0,W):
                    try:
                        hand.remove(f+i)
                    except:
                        return False
            return True

class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        # Edge case: len(hand)%W!=0 that means it's not possible to split into W sized groups.
        # we can try to arrange them in form of HashMap, 
        # 1:1, 2:2, 3:3, 4:4 
        # if we sort them and try to find the counts, if count[i-1]>count[i] then FALSE
        # [1,2,3,6,2,3,4,7,8]
        # {1:1, 2:2, 3:2, 4:1, 6:1,7:1,8:1}
        if len(hand)%W!=0:
            return False
        else:
            while(hand!=[]):
                minele = min(hand)
                for i in range(0, W):
                    try:
                        hand.remove(minele+i)
                    except:
                        return False
            return True


import heapq
import collections

class Solution:
    def isNStraightHand(self, hand, W) -> bool:
        if len(hand) % W != 0:
            return False

        counter_map = collections.Counter(hand)
        counter = 0
        heapq.heapify(hand)

        while hand:
            min_val = heapq.heappop(hand)
            next_val = min_val + 1
            counter += 1
            while counter < W and counter_map.get(next_val, 0) > 0:
                counter_map[next_val] -= 1
                hand.remove(next_val)
                counter += 1
                next_val += 1

            # Cannot split anymore
            if counter < W:
                return False

            # resetting counter
            counter = 0
            heapq.heapify(hand)

        return True

class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        if len(hand) < W or len(hand) % W != 0:
            return False
        d = {}
        for i in hand:
            d[i] = d.get(i,0) +1
        keys = sorted(list(d.keys()))
        for i in keys:
            if d[i] == 0:
                continue
            while d[i] > 0:
                for j in range(i,i+W):
                    if j not in keys or d[j] <=0:
                        return False
                    else:
                        d[j] = d[j] -1
        return True

class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        c = collections.Counter(hand)
        for i in sorted(c):
            if c[i] > 0:
                for j in range(W)[::-1]:
                    c[i + j] -= c[i]
                    if c[i + j] < 0:
                        return False
        return True

from collections import Counter
class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        if len(hand) % W:
            return False
        cnt = Counter(hand)
        cards = sorted(cnt)
        while True:
            first = cards.pop()
            if not cnt[first]:
                continue
            amount = cnt[first]
            del cnt[first]
            for i in range(first - 1, first - W, -1):
                if not cnt[i]:
                    return False
                cnt[i] -= amount
                if cnt[i] < 0:
                    return False
                elif cnt[i] == 0:
                    del cnt[i]
            if not cnt:
                return True
        return False # never happen

class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        count = collections.Counter(hand)
        dic = {k: v for k, v in sorted(count.items())}
        while dic:
            m = next(iter(dic))
            #print(m)
            for k in range(m, m+W):
                v = dic.get(k)
                #print(v,k)
                if not v: 
                    return False
                if v == 1:
                    del dic[k]
                else:
                    dic[k] = v - 1

        return True

class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        n = len(hand)
        if n % W != 0:
            return False
        
        counter = Counter(hand)
        
        nums = sorted(counter.keys())
        
        for num in nums:
            count = counter[num]
            if count == 0:
                continue
            min_count = count
            for i in range(W):
                if count[num+i] < min_count:
                    return False
                count[num+i] -= min_count
        return True
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        #[1,2,3,2,3,4]
        #[1,2,2,3,3,4]
        
        if len(hand) % W != 0:
            return False
        
        counter = Counter(hand)
        q = []
        for num, freq in list(counter.items()):
            heapq.heappush(q, (num, freq))

        while q and len(q) >= W:
            tmp = []
            for i in range(W):
                x = heapq.heappop(q)
                if tmp and tmp[-1][0]+1 != x[0]:
                    return False
                tmp.append(x)
            for num, freq in tmp:
                if freq > 1:
                    heapq.heappush(q, (num, freq-1))
        return 0 == len(q)
            

            
            
    def isNStraightHand4(self, hand: List[int], W: int) -> bool:
        #[1,2,3,2,3,4]
        #[1,2,2,3,3,4]
        
        if len(hand) % W != 0:
            return False

        hand.sort()
        q = []
        for num in hand:
            if q and q[-1][0] == num:
                q[-1][1] += 1
            else:
                q.append([num, 1])

        #[[3,3]]
        #
        n = len(hand)
        while n > 0:
            if len(q) < W:
                return False
            for i in range(1, W):
                if q[i][0] != q[i-1][0] + 1:
                    return False
            j = 0
            #print(j)
            for i in range(W):
                #print(i)
                if q[j][1] == 1:
                    q.pop(j)
                else:
                    q[j][1] -= 1
                    j += 1
            n -= W
        return len(q) == 0

    def isNStraightHand3(self, hand: List[int], W: int) -> bool:
        counter = Counter(hand)
        while counter:
            m = min(counter)
            for k in range(m, m+W):
                v = counter[k]
                if not v: return False
                if v == 1:
                    del counter[k]
                else:
                    counter[k] = v - 1
        return True


class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
  
        hand.sort()
        while(len(hand)>0):
        
            val=hand.pop(0)
            for j in range(W-1):
                try:
                    val+=1
                    indx=hand.index(val)
                    hand.pop(indx)
                except:
                    return False
        return True
                    


## time - O(MlogM + M), space - O(M)
from collections import Counter, deque
class Solution:
    def isNStraightHand(self, hand, W):
        cnts = Counter(hand)
        for num in sorted(cnts):
        
            tmp = cnts[num]
            if tmp > 0:
                for j in range(num, num+W):
                    cnts[j] -= tmp
                    if cnts[j] < 0:
                        return False
        return True
 #for example, hand = [1,2,3,6,2,3,4,7,8], W = 3
#cnts: {1:1,2:2,3:2,4:1,6:1,7:1,8:1}
#=>{1:0,2:1,3:1,4:1,6:1,7:1,8:1}
#=>{1:0,2:0,3:0,4:0,6:1,7:1,8:1}
#=>{1:0,2:0,3:0,4:0,6:0,7:0,8:0}


class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        count_map = Counter()
        for num in hand:
            count_map[num] += 1
        test = sorted(count_map)
        sorted_hand = sorted(dict.fromkeys(hand))
        while len(sorted_hand) > 0:
            while len(sorted_hand) > 0 and count_map[sorted_hand[0]] == 0:
                sorted_hand.pop(0)
            if len(sorted_hand) > 0:
                for key in range(sorted_hand[0], sorted_hand[0]+W):
                    if key in count_map:
                        count_map[key] -= 1
                        if count_map[key] < 0:
                            return False
                    else:
                        return False
        return True

from collections import Counter
class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        cards = Counter(hand)
        for card in sorted(hand):
            if cards[card] > 0:
                for i in range(W):
                    if card + i not in cards or cards[card + i] == 0:
                        return False
                    cards[card + i] -= 1
        return True

class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        if len(hand) == 0:
            return False
        if len(hand) % W > 0:
            return False
        count = {}
        for n in hand:
            if n not in count:
                count[n] = 1
            else:
                count[n] += 1
                
        total = sum(count.values())
        for n in sorted(hand):
            if total == 0:
                break
            if count[n] == 0:
                continue
            for i in range(W):
                target = n + i
                if target in count and count[target] > 0:
                    count[target] -= 1
                    total -= 1
                else:
                    return False
        return True


class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        hand.sort()
        while hand:
            curr = hand[0]
            try:
                for i in range(W):
                    hand.remove(curr)
                    curr += 1
            except:
                return False
        return True

class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        hand.sort()
        while hand:
            try:
                base = hand[0]
                for i in range(W):
                    hand.remove(base + i)
            except:
                return False
        return True

class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        n = len(hand)
        if n % W:
            return False
        
        C = Counter(hand)
        keys = sorted(C.keys())
        #output = []
        for i in range(n//W):
            mn = keys[0]
        #    straight = []
            for j in range(mn, mn + W):
                if j not in keys:
                    return False
                else:
                    C[j] -= 1
        #            straight.append(j)
                    if C[j] == 0:
                        del C[j]
                        keys.remove(j)
        #    output.append(straight)
        #print (output)
        return True


class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        if len(hand)%W!=0:
            return False
        
        hand=sorted(hand)
        dct={}
        for x in hand:
            if x not in dct:
                dct[x]=1
            else:
                dct[x]+=1
                
        while len(hand)>0:
            group=[hand[0]]
            check=hand[0]
            hand.remove(check)
            while len(group)<W:
                if check+1 not in dct or dct[check+1]<1:
                    return False
                group.append(check+1)
                hand.remove(check+1)
                dct[check+1]-=1
                check+=1
        return True

from collections import Counter
class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        counter = Counter(hand)
        for key in sorted(counter):
            if counter[key] > 0:
                for i in range(1, W):
                    counter[key + i] -= counter[key]
                    if counter[key + i] < 0:
                        return False
                counter[key] = 0
        return True

class Solution:
  # 204 ms
  def isNStraightHand(self, hand, W):
    nums = len(hand)
    if nums % W: return False
    elif W == 1: return True
    else:
      heapify(hand)
      arrange = deque() # collect group
      lastOp = [0,-1] # lastOp = [i, h]: record the operation of last time
      groups = 0 # count group
      while hand:
        h = heappop(hand)
        i = 0
        # if the same card as last time, escalate i
        if h == lastOp[1]: i = lastOp[0] + 1
        # add new group
        if len(arrange) < i+1:
          arrange.append([])
          groups += 1
        # num of group should be nums//W
        if groups > nums//W: return False
        # if not consecutive, False
        if len(arrange[i]) and arrange[i][-1] +1 != h:
          return False
        else:
          # arrange new card if group size is less than W
          arrange[i].append(h)
          lastOp = [i, h]
        # pop group if size is full
        if len(arrange[i]) == W:
          arrange.popleft()
          lastOp = [0, -1]

    return True

class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        if not hand:
            return False
        if len(hand) % W != 0:
            return False
  
        hand.sort()
        n = len(hand)
        dic = Counter(hand)
        cards = list(dic.keys())
        cards.sort()
  
  
        for c in cards:
            num = dic[c]
            if num == 0:
                continue
            for i in range(1, W):
                if (c + i) in dic and dic[c+i] >= num:
                    dic[c+i] -= num
                else:
                    return False
  
        return True

class Solution:
  # 204 ms
  def isNStraightHand(self, hand, W):
    nums = len(hand)
    if nums % W: return False
    elif W == 1: return True
    else:
      heapify(hand)
      arrange = deque() # collect group
      lastOp = [0,-1] # lastOp = [i, h]: record the operation of last time
      groups = 0 # count group
      while hand:
        h = heappop(hand)
        i = 0
        # if the same card as last time, escalate i
        if h == lastOp[1]: i = lastOp[0] + 1
        # add new group
        if len(arrange) < i+1:
          arrange.append([])
          groups += 1
        # num of group should be nums//W
        if groups > nums//W: return False
        # arrange new card if group size is less than W
        if len(arrange[i]) < W:
          arrange[i].append(h)
          lastOp = [i, h]
        # not consecutive, False
        if len(arrange[i]) > 1 and arrange[i][-2] + 1 != arrange[i][-1]:
          return False
        # pop group if size is full
        if len(arrange[i]) == W:
          arrange.popleft()
          lastOp = [0, -1]

    return True

from collections import Counter
class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        count = Counter(hand)
        for i in sorted(count):
            if count[i] > 0:
                for j in range(W-1, -1, -1):
                    count[i+j] -= count[i]
                    if count[i+j] < 0:
                        return False
        return True


class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        heapq.heapify(hand)
        
        while hand:
            last_item = heapq.heappop(hand)
            leftover = []
            
            for _ in range(W - 1):
                if not hand:
                    return False
                
                next_item = heapq.heappop(hand)
                
                while next_item == last_item:
                    leftover.append(next_item)
                    if not hand:
                        return False
                    next_item = heapq.heappop(hand)
                    
                if next_item > last_item + 1:
                    return False
                
                last_item = next_item
                
            for item in leftover:
                heapq.heappush(hand, item)
                
        return True

class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        if len(hand)%W: return False
        if W==1: return True
        counts=collections.Counter(hand)
        for num in sorted(hand):
            if not counts[num]: continue
            for next in range(num,num+W):
                if next not in counts or not counts[next]: return False
                counts[next]-=1
        return True

class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        if len(hand) % W != 0:
            return False
        
        #use dictionary to do quick look-up
        dic = {}
        
        for num in hand:
            if num not in dic:
                dic[num] = 1
            else:
                dic[num] += 1
        
        hand.sort()
        
        while len(hand) > 0:
            smallest = hand[0]
            dic[smallest] -= 1
            for i in range(1,W):
                check = smallest + i
                if check not in dic:
                    return False
                else:
                    if dic[check] <= 0:
                        return False
                    else:
                        dic[check] -= 1
                        hand.remove(check)
            hand.remove(smallest)
            
        return True
            
            


class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        
        hand.sort()
        
        count = {}
        for h in hand:
            if h not in count:
                count[h] = 1
            else:
                count[h] += 1
        
        key = list(count.keys())
        print(count)
        
        head = 0
        while head < len(key):
            this_key = key[head]
            if count[this_key] == 0:
                head += 1
                continue
            tail = head + 1
            
            while tail < len(key) and tail < head + W:
                if count[key[tail]] >= count[this_key] and key[tail] == key[tail - 1] + 1:
                    count[key[tail]] -= count[this_key]
                else:
                    return False
                tail += 1
            if tail < head + W:
                return False
            count[this_key] = 0
            head += 1
            
        return True

class Solution:
  def isNStraightHand(self, hand, W):
    nums = len(hand)
    if nums % W: return False
    elif W == 1: return True
    else:
      heapify(hand)
      arrange = [[] for _ in range(nums//W)] 
      start = 0
      while hand:
        h = heappop(hand)
        i = start
        while True:
        #  print(h, i, arrange)
          if len(arrange[i]) == W:
            i += 1
            start = i
          if len(arrange[i]) == 0 or (arrange[i] and arrange[i][-1] != h):
            arrange[i].append(h)
          elif arrange[i] and arrange[i][-1] == h:
            if i+1 == len(arrange):
              return False
            i += 1
            continue
          if len(arrange[i]) > 1 and arrange[i][-2] + 1 != arrange[i][-1]:
            return False
          else:
            break

          #  return 
    return True #arrange

class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        straights, pq, = [], []
        for h in hand:
            heapq.heappush(pq, h)
        while len(pq) > 0:
            straight, dump = [], []
            while len(pq) > 0 and len(straight) < W:
                pop = heapq.heappop(pq)
                if len(straight) == 0 or pop == straight[-1] + 1:
                    straight.append(pop)
                else:
                    dump.append(pop)
            straights.append(straight) 
            if len(straight) < W:
                return []
            else:
                for d in dump:
                    heapq.heappush(pq, d)
        
        #print(\"hel\")
        #print(straights)   
        return len(straights) > 0 

class Solution:
  # 184 ms
    def isNStraightHand(self, h, W):       
        l = len(h)
        if l % W != 0:
            return False    
        heapify(h)
        c = Counter(h)
        
        for _ in range(l // W):
          x = heappop(h)
          while c[x] == 0:
            x = heappop(h)
            
          for _ in range(W):
            if c[x] == 0:
              return False
            c[x] -= 1
            x += 1
                
        return True

class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        c = collections.Counter(hand)
        for i in sorted(c):
            if c[i] > 0:
                for j in range(W)[::-1]:
                    c[i + j] -= c[i]
                    
                    if c[i + j] < 0:
                        return False
        return True

class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        if len(hand)%W != 0:
            return False
        i = 0
        hand.sort()
        while hand:
            for j in range(1, W):
                if hand[i]+j not in hand:
                        return False  
                hand.pop(hand.index(hand[i]+j))
            hand.pop(i)
        return True

class Solution:
  # 204 ms
  def isNStraightHand(self, hand, W):
    nums = len(hand)
    if nums % W: return False
    elif W == 1: return True
    else:
      heapify(hand)
      arrange = deque() # collect group
      lastOp = [0,-1] # lastOp = [i, h]: record the operation of last time
      groups = 0 # count group
      while hand:
        h = heappop(hand)
        i = 0
        # if the same card as last time, escalate i
        if h == lastOp[1]: i = lastOp[0] + 1
        # add new group
        if len(arrange) < i+1:
          arrange.append([])
          groups += 1
        # num of group should be nums//W
        if groups > nums//W: return False
        # not consecutive, False
        if len(arrange[i]) and arrange[i][-1] +1 != h:
          return False
        else:
          # arrange new card if group size is less than W
          arrange[i].append(h)
          lastOp = [i, h]
        # pop group if size is full
        if len(arrange[i]) == W:
          arrange.popleft()
          lastOp = [0, -1]

    return True

class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        if len(hand) % W != 0:
            return False
        hand.sort()
        while hand:
            start = hand[0]
            hand.remove(start)
            for i in range(W-1):
                start += 1
                if start in hand:
                    hand.remove(start)
                else:
                    return False
        return len(hand) == 0
        



class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        if len(hand) % W:
            return False
        hand.sort()
        while hand:
            try :
                base = hand[0]
                for i in range(W):
                    hand.remove(base + i)
            except:
                return False

        return True






        


class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        from collections import Counter
        c = Counter(sorted(hand))
        for i in c:
            if c[i] == 0:
                continue
            for j in range(1, W):
                if c[i + j] >= c[i]:
                    c[i + j] -= c[i]
                else:
                    return False
            c[i] -= c[i]
        return True

class Solution:
    def isNStraightHand(self, h: List[int], W: int) -> bool:
        
        l = len(h)
        if l % W != 0:
            return False
        
        heapify(h)
        c = Counter(h)
        
        for _ in range(l // W):
            
            x = heappop(h)
            while c[x] == 0:
                x = heappop(h)
            
            for _ in range(W):
                
                if c[x] == 0:
                    return False
                c[x] -= 1
                x += 1
                
        return True

import collections
import heapq
class Solution:
    def checkConsecutives(self, nums):
        pos = 0
        while pos < len(nums)-1:
            if nums[pos][0]+1 != nums[pos+1][0]:
                return False
            pos += 1
        return True
    
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        if len(hand)%W!=0:
            return False
        
        min_heap = []
        heapq.heapify(min_heap)
        num_dict = collections.Counter(hand)
        for key, val in list(num_dict.items()):
            heapq.heappush(min_heap, (key, val))
            
        while min_heap:
            consec = []
            for _ in range(W):
                if not min_heap:
                    return False
                consec.append(list(heapq.heappop(min_heap)))
            
            if self.checkConsecutives(consec):
                pos = 0
                while pos<len(consec):
                    if consec[pos][1]-1<=0:
                        consec.pop(pos)
                        continue
                    else:
                        consec[pos][1] -= 1
                    pos += 1
                pos = 0
                while pos<len(consec):
                    heapq.heappush(min_heap, tuple(consec[pos]))
                    pos += 1
            else:
                return False
        return True


class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        n = len(hand)
        if n % W:
            return False
        
        C = Counter(hand)
        keys = sorted(C.keys())
        output = []
        for i in range(n//W):
            mn = keys[0]
            straight = []
            for j in range(mn, mn + W):
                if j not in keys:
                    return False
                else:
                    C[j] -= 1
                    straight.append(j)
                    if C[j] == 0:
                        del C[j]
                        keys.remove(j)
            output.append(straight)
        print (output)
        return True


class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        if not hand or len(hand) % W != 0: return False
        
        counter = Counter(hand)
        for c in sorted(counter):
            if counter[c] > 0:
                for i in range(W)[::-1]:
                    counter[c+i] -= counter[c]
                    if counter[c+i] < 0: return False
        return True


class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        hand.sort()
        if len(hand)%W==0:
            while len(hand)!=0:
                head=hand.pop(0)
                for i in range(1,W):
                    if head+i in hand:
                        hand.remove(head+i)
                    else:
                        return False
            return True
                    
        else:
            return False

class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        if len(hand)%W!=0:
            return False
        
        hand=sorted(hand)
        dct={}
        for x in hand:
            if x not in dct:
                dct[x]=1
            else:
                dct[x]+=1
                
        '''
        below is O(N^2)? so TOO SLOW
        see https://leetcode.com/problems/hand-of-straights/discuss/135598/C%2B%2BJavaPython-O(MlogM)-Complexity
        for O(NlogN) soln
        '''        
        while len(hand)>0:
            group=[hand[0]]
            check=hand[0]
            hand.remove(check)
            while len(group)<W:
                if check+1 not in dct or dct[check+1]<1:
                    return False
                group.append(check+1)
                hand.remove(check+1)
                dct[check+1]-=1
                check+=1
        return True

class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        hand.sort()
        if len(hand) % W !=0:
            return False
        
        else:
            for i in range(len(hand) // W):
                tmp=hand.pop(0)
                for j in range(W-1):
                    if tmp+j+1 in hand:
                        hand.pop(hand.index(tmp+j+1))
                    else:
                        return False
            print(hand)
            if len(hand) == 0:
                return True
            else:
                return False
                        


class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        if not hand: return W==0
        if len(hand)%W!=0: return False
        hand.sort()
        
        def isnstraighthand(li):
            if not li: return True
            start = li[0]
            for i in range(start,start+W):
                if i not in li:
                    return False
                else:
                    li.remove(i)
            return isnstraighthand(li)
        
        return isnstraighthand(hand)


class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        if (len(hand) % W != 0):
            return False
        hand.sort()
        length = len(hand)
        count = 0
        group = []
        while(1):
            for i in range(W-1):
                if ((hand[0]+i+1) in hand):
                    count += 1
                    hand.pop(hand.index(hand[0]+i+1))          
                else:
                    return False
            hand.pop(0)
            if len(hand) == 0:
                return True

class Solution:
    import heapq
    # https://www.youtube.com/watch?v=Zz7BWDY5kvM&list=UUSYPN_WIvDy4spjxzdevk6Q
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        if W == 1:
            return True
        if len(hand) % W:
            return False
        hand.sort()
        heap = []
        for n in hand:
            if not heap:
                heapq.heappush(heap, (n, 1))
            else:
                curr, size = heap[0]
                if n == curr:
                    heapq.heappush(heap, (curr, 1))
                elif n == curr + 1:
                    heapq.heappop(heap)
                    size += 1
                    if size < W:
                        heapq.heappush(heap, (n, size))
                else:
                    return False
        return bool(not heap)


from collections import OrderedDict 

class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        
        if len(hand) % W != 0:
            return False
        
        card_counts = OrderedDict()     
        
        for i in range(len(hand)):
            card_counts[hand[i]] = card_counts.get(hand[i], 0) + 1
        
        
        keys = sorted(card_counts.keys())
                
        while card_counts:
            min_val =  keys[0]
            for hand in range(min_val, min_val+W):
                #print(hand[i])
                #print(card_counts)
                if hand not in card_counts:
                    return False
                
                count = card_counts[hand]
                if count == 1:
                    keys.pop(0)
                    del card_counts[hand]
                else:
                    card_counts[hand] -= 1
        
        
        return True

class Solution:
    import heapq
    def isNStraightHand(self, hand, W):
        heapq.heapify(hand)
        while len(hand) > 0:
            put_back =  []
            count = 0
            prev = hand[0] - 1
            while count < W:
                if len(hand) == 0:
                    return False
                v = heapq.heappop(hand)
                if v != prev + 1:
                    put_back.append(v)
                else:
                    prev = v
                    count += 1

            for element in put_back:
                heapq.heappush(hand, element)
        return True

class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        hmap = {}
        for h in hand : 
            if h not in hmap : hmap[h] = 0
            hmap[h] +=1
        
        cards = sorted(list(hmap.keys()))
        #print(hmap,cards)
        
        for card in cards :
            #print(hmap)
            while card in hmap :
                for n in range(card,card+W) :
                    if n not in hmap : 
                        #print(hmap,\"pop\",n,card)
                        return False
                    else : 
                        hmap[n] -=1
                        if hmap[n] == 0 : 
                            
                            del(hmap[n])
                            #print(hmap,\"pop\",n,card)
        #print(hmap,\"k\")
        if hmap : return False 
        return True

class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        if not hand: return False
        
        hand = sorted(hand)
        queue, rs, group = [], [], []
        while hand:
            card = hand.pop(0)
            if not group or group[-1] == card - 1:
                group.append(card)
                if len(group) == W:
                    hand = queue + hand 
                    rs.append(group)
                    group, queue = [], []
            else:
                queue.append(card)
        
        if not group and not queue:
            return True 
        else:
            return False

class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        n = len(hand)
        if n % W != 0:
            return False
        hand.sort()
        for i in range(n // W):
            start = hand[0]
            hand.remove(start)
            for j in range(W - 1):
                if start + j + 1 in hand:
                    hand.remove(start + j + 1)
                else:
                    return False
        return True

from collections import Counter
class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        n = len(hand) 
        if n % W != 0:
            return False
        
        
        occurmap = Counter(hand)
        
         
        tots = 0
        hand.sort()
        # print('hnd is ', hand)
        for i in range(n):
            v = hand[i]
            if occurmap[v-1] > 0 or occurmap[v] <= 0:
                continue
            # print('first value is ', v) 
            
            count = 1
            occurmap[v] -= 1
            while count < W and occurmap[v+1] > 0:
                count += 1
                occurmap[v+1] -= 1
                v = v+1
            # print(occurmap)
            # print('for ', v)
            # print('count is ', count)
            if count == W:
                tots += 1
            
        # print('tots is ', tots)
        if tots * W == n:
            return True
        return False


class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        if ((len(hand) % W) != 0):
            return False
        sorted_hand = hand
        sorted_hand.sort()
        num_groups = int(len(hand)/W)
        for i in range (num_groups):
            num = sorted_hand[0]
            sorted_hand.remove(num)
            for j in range (W-1):
                num += 1
                if num in sorted_hand:
                    sorted_hand.remove(num)
                else:
                    return False
        return True


class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        hand.sort()
        while hand:
            try:
                base = hand[0]
                for i in range(W):
                    hand.remove(base+i)
            except:
                return False
        return True

class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        if len(hand) % W != 0:
            return False
        
        counter, smallest = self.counter(hand)
        
        for _ in range(len(hand) // W):
            if smallest is None:
                smallest = min(counter)
            curr = smallest
            counter[curr] -= 1
            if counter[curr] == 0:
                del counter[curr]
                smallest = None
            for _ in range(W - 1):
                curr = curr + 1
                if curr not in counter:
                    return False
                else:
                    counter[curr] -= 1
                    if counter[curr] == 0:
                        del counter[curr]
                    elif smallest is None:
                        smallest = curr
        return True

    def counter(self, array):
        smallest = None
        counter = {}
        for el in array:
            if el in counter:
                counter[el] += 1
            else:
                counter[el] = 1
                if smallest is None or el < smallest:
                    smallest = el
        return counter, smallest






class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        # Q: repititions allowed? yes 
        # Q: negative numbers allowed? no 
        # brute force: make a hashmap with the key as hand[i] and value as frequency: O(n)
        # maintain a sorted list of indexes: O(n*log(n))
        # make a pass over the sorted list of indexes, and move to next when the frequency goes to 0 -> O(n)
        # time complexity = O(n*log(n))
        if (W==1):
            return True 
        sorted_indexes = []
        frequency_map = {}
        for h in hand: 
            if h not in list(frequency_map.keys()):
                frequency_map[h] = 1
                # add to sorted list 
                self.addToSortedList(h, sorted_indexes)       
            else: 
                frequency_map[h] += 1
                
        print((sorted_indexes, frequency_map))
        # using frequency_map, and sorted_indexes, check if consecutive lists can be made 
        index = 0
        while index < len(sorted_indexes):
            # start the current W length list with sorted_indexes[index]        
            for ele in range(sorted_indexes[index], sorted_indexes[index]+W):
                if ele not in list(frequency_map.keys()) or frequency_map[ele] == 0:
                    return False
                
                frequency_map[ele] -= 1
            while (index < len(sorted_indexes) and frequency_map[sorted_indexes[index]] == 0):
                # remove the element from frequency_map
                frequency_map.pop(sorted_indexes[index])
                index += 1
                
        return len(list(frequency_map.keys())) == 0 
        
    def addToSortedList(self, value: int, sorted_list: List[int]):
        # values are not repeated in the sorted list 
        if (len(sorted_list) == 0):
            sorted_list.append(value)
            return
        #print(\"---> val:\" + str(value))
        low = 0 
        high = len(sorted_list) - 1
        while (low < high):
            mid = math.floor((low+high)/2)
            #print(mid, low, high)
            if value < sorted_list[mid]:
                high = mid - 1
            elif value > sorted_list[mid]:
                low = mid + 1
        #print(value, low, high, sorted_list)
        if high < 0:
            sorted_list.insert(0, value)
        elif value > sorted_list[high]:
            sorted_list.insert(high+1, value)
        else:
            sorted_list.insert(high, value)


class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        ogLen = len(hand)
        if W == 1:
            return True
        
        counter = Counter(hand)
        counted = [(key, counter[key]) for key in counter]
        counted.sort()
        
        print(counted)
        
        heapify(counted)
        
        groups = []
        
        
        
        
        group = []
        group.append(heappop(counted))
        
        tempStorage = set()
        
        while counted:
            
            n0 = group[-1]
            
            # print(n0[0], counted[0][0], group)
            
            if n0[0]+1 == counted[0][0]:
                n1 = heappop(counted)
                
            elif counted[0][0] > n0[0]+1:
                
                group = []
                group.append(heappop(counted))
                continue
            
            group.append(n1)
            
            if len(group) == W:
                # print(\"adding group\", group)
                groups.append(group)
                
                for val, count in group:
                    count -= 1
                    if count != 0:
                        heappush(counted, (val, count))
                
                # print(\"heap now: \", counted)
                group = []
                if counted:
                    group.append(heappop(counted))

        print((len(groups)*W, ogLen))
                
        return len(groups)*W == ogLen
            
            
            
            
            


from collections import defaultdict

class Solution:
    def isNStraightHand(self, hand: List[int], k: int) -> bool:
        if len(hand) < k or len(hand) % k != 0:
            return False
        if k == 1:
            return True
        hand.sort()
        
        queue = deque(hand)
        q2 = deque()
        
        currVal = -1
        currNum = 0
        for i in range(len(hand) // k):
            while currNum < k:
                if not queue:
                    return False
                if currVal == -1:
                    currVal = queue.popleft()
                    currNum += 1
                    continue
                val = queue.popleft()
                if val == currVal + 1:
                    currVal = val
                    currNum += 1
                elif val > currVal + 1:
                    return False
                elif val == currVal:
                    q2.append(val)

            queue = q2 + queue
            q2 = deque()
            currVal = -1
            currNum = 0
        return True
        
        


from collections import Counter
class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        cs = Counter(hand)
        
        for card in hand: 
            if not cs[card] or cs[(card:=card-1)]:
                continue
            
            l = -1
            while (l:=l+1) < W and cs[(card:=card+1)]:
                cs[card] -= 1
                if cs[card] == 0: del cs[card]
            
            if l != W:
                return False
        
        return True  
        


from collections import defaultdict
class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        if len(hand) % W != 0:
            return False
        if W == 1:
            return True
        
        hand.sort()
        freq = defaultdict(int)
        for c in hand:
            freq[c] += 1

        while len(freq) != 0:
            keys = list(freq.keys())
            if len(keys) < W:
                return False
            for i in range(W-1):
                if keys[i] + 1 != keys[i+1]:
                    return False
                freq[keys[i]] -= 1
                if freq[keys[i]] == 0:
                    freq.pop(keys[i])
                if i == W-2:
                    freq[keys[i+1]] -= 1
                    if freq[keys[i+1]] == 0:
                        freq.pop(keys[i+1])
        
        return True

class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:

        if (len(hand) % W) != 0:
            return False
        
        hand.sort()
        c = Counter(hand)
        
        for i in range(len(hand) // W):
            
            if len(hand) < W:
                return False
            
            keys = list(c.keys())
            key = keys[0]
            
            for j in range(W):
                if key not in c:
                    return False
                
                if c[key] == 1:
                    del c[key]
                    key += 1
                    
                else:
                    c[key] -= 1
                    key += 1
                    
        return True

class Solution:
    def isNStraightHand(self, hand: List[int], w: int) -> bool:
        d={}
        for i in hand:
            if(i not in d):
                d[i]=1
            else:
                d[i]+=1
        d=sorted(list(d.items()),key= lambda x:x[0])
        d1={}
        for i in d:
            d1[i[0]]=i[1]
        
        while(len(d1)>0):
            r=list(d1.keys())[0]
         
            for i in range(r,r+w):
                if(i not in d1):
                    return False
                count=d1[i]
                if(count==1):
                    d1.pop(i)
                else:
                    d1[i]=d1[i]-1
        return True


class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        
        d = {}
        for i in hand:
            if i in d:
                d[i] += 1
            else:
                d[i] = 1
        
        sd = {k: v for k, v in sorted(list(d.items()), key=lambda item: item[0])}
        
        while sd:
            keys = list(sd.keys())
            i = keys[0]
            sd[i] -= 1
            if sd[i] == 0: del sd[i]
            count = 1
            while count < W:
                if (i+count) not in sd:
                    return False
                else:
                    sd[i+count] -= 1
                    if sd[i+count] == 0: del sd[i+count]
                count += 1
        return True


class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        if len(hand)%W != 0:
            return False
        hand.sort()
        count = collections.Counter(hand)
        while count:
            key = list(count.keys())[0]
            for i in range(W):
                if count[key+i] > 0:
                    count[key+i] -= 1
                    if count[key+i] == 0:
                        del count[key+i]
                else:
                    return False
        return True

class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        from collections import Counter
        
        i = 0
        hand.sort()
        hand_count = Counter(hand)
        
        while i < len(hand):
            if hand[i] not in hand_count:
                i += 1
            else: 
                cur = hand[i]
                for j in range(W):
                    if not hand_count[cur+j]:
                        return False

                    hand_count[cur+j] -= 1

                    if hand_count[cur+j] == 0:
                        del hand_count[cur+j]

                i += 1

            
        return True


class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        hand = sorted(hand)
        counter = collections.Counter(hand)
        while counter:
            m = min(counter)
            for i in range(W):
                num = m + i
                if num in counter:
                    counter[num] -= 1
                    if counter[num] == 0: del counter[num]
                else:
                    return False
        return True
                    
                


class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        if len(hand) % W != 0:
            return False
        hand_count = {}
        for x in hand:
            if x not in hand_count:
                hand_count[x] = 1
            else: 
                hand_count[x] += 1
                
        while len(hand_count) > 0:
            min_key = min(hand_count.keys())
            min_key_count = hand_count[min_key]
            for i in range(W):
                key = min_key + i 
                if key not in hand_count:
                    return False
                hand_count[key] -= min_key_count
                if hand_count[key] == 0:
                    del hand_count[key]
                elif hand_count[key] < 0:
                    return False
        return True


class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        count = collections.Counter(hand)
        
        while count:
            n = min(count.keys())
            n_count = count[n]
            for x in range(n + 1, n + W):
                if count[x] < n_count:
                    return False
                count[x] -= n_count
                if count[x] == 0:
                    count.pop(x)
            count.pop(n)
        
        return True
            
            


from collections import Counter
class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        count = collections.Counter(hand)
        while count:
            m = min(count)
            for k in range(m, m+W):
                v = count[k]
                if not v: return False
                if v == 1:
                    del count[k]
                else:
                    count[k] = v - 1

        return True

class Solution(object):
    def isNStraightHand(self, hand, W):
        if len(hand) % W != 0: return False
        count = collections.Counter(hand)
        while count:
            m = min(count.keys())
            num = count[m]
            for k in range(m, m+W):
                v = count[k]
                if v < num: return False
                if v == num:
                    del count[k]
                else:
                    count[k] = v - num

        return True


class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        
        counter = collections.Counter(hand)
        
        while counter:
            m = min(counter)
            for k in range(m, m+W):
                v = counter[k]
                if not v: return False
                if v == 1:
                    del counter[k]
                else:
                    counter[k] = v -1
        return True


class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        if len(hand)%W!=0:
            return False
        
        dicts={}
        for n in hand:
            dicts[n]=dicts.get(n,0)+1
        
        while dicts:
            # print(min(dicts),max(dicts))
            m=min(dicts)
            for k in range(m,m+W):
                # print('m-m+W:',m,m+W)
                if k not in dicts: return False
                elif dicts[k]==1:
                    del dicts[k]
                else:
                    dicts[k]-=1
                    
        return True

class Solution:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        counter = collections.Counter(hand)
        while counter:
            num = min(counter)
            for i in range(num, num + W):
                if i not in counter:
                    return False
                elif counter[i] == 1:
                    del counter[i]
                else:
                    counter[i] -= 1
                    
        return True

class Solution:
    def isNStraightHand(self, nums: List[int], k: int) -> bool:
        
        n = len(nums)
        
        if n % k != 0:
            return False
        
        cnt = Counter(nums)
        no = min(cnt.keys())
        while cnt: 
            for j in range(k):
                if cnt[no] == 0:
                    return False
                
                cnt[no] -= 1
                if cnt[no] == 0:
                    cnt.pop(no)
                
                no += 1
            
            if cnt:
                no = min(cnt.keys())
           
        
        return True