The problem is as follow:
Our input is an array of 14 numbers and our output is whether this is a winning hand. For a hand to be a winning hand it must be possible to divide its numbers into groups with the following rules:
- Each group of 3 must be of identical numbers or a straight (111 or 123)
- We are allowed to have only 1 pair of identical numbers (22 is OK but 45 is not)
For example:
[1,1,1,2,2,2,3,3,3,4,4,4,5,5]: True
[1,1,1,2,2,2,3,3,3,4,4,4,5,6]: False
[1,1,2,2,3,3,4,4,4,6,6,6,8,8]: True
I wrote the following solution for problem using a backtracking technique:
Note: Ignore all occurrence of seen
it is part of the memorization for the second part of my question below.
def is_winning_hand(hand):
hand.sort()
seen = set()
return is_winning_hand_step(hand, True, seen)
def is_winning_hand_step(hand, can_take_two, seen):
if len(hand) == 0:
return True
if len(hand) == 1:
return False
if str(hand)+str(can_take_two) in seen:
return False
if can_take_two:
valid, new_hand = take_two(hand)
if valid:
if is_winning_hand_step(new_hand, False, seen):
return True
if len(hand) >= 3:
valid, new_hand = take_three(hand)
if valid:
if is_winning_hand_step(new_hand, can_take_two, seen):
return True
valid, new_hand = take_straight(hand)
if valid:
if is_winning_hand_step(new_hand, can_take_two, seen):
return True
seen.add(str(new_hand)+str(can_take_two))
return False
def take_two(hand):
if hand[0] == hand[1]:
return True, hand[2:]
else:
return False, None
def take_three(hand):
if hand[0] == hand[1] and hand[1] == hand[2]:
return True, hand[3:]
else:
return False, None
def take_straight(hand):
cnt = 1
last_val = hand[0]
indices = set([0])
for i in xrange(1, len(hand)):
if hand[i] == last_val:
continue
elif hand[i] == last_val + 1:
cnt += 1
indices.add(i)
last_val = hand[i]
if cnt == 3:
return True, [x for j, x in enumerate(hand) if j not in indices]
else:
return False, None
return False, None
Now I am trying to find out what is the time complexity of that problem.
Let's assume the input is already sorted for us so leave aside it's O(N log N)
.
My guess is since in each step I have a potential split to 3 branches the complexity is O(3^N)
where N should be the length of the input array. In our case it is always 14 length array but I am talking about the general case. Am I correct?
In the next step I added a memorization to my solution. What can we tell about the time complexity now? Thanks to the memorization I'm avoiding from solving the same sub-problems again and again, so is that making it an O(N)
solution?