微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

带和不带记忆的回溯算法的复杂性

如何解决带和不带记忆的回溯算法的复杂性

问题如下:

我们的输入是一个包含 14 个数字的数组,我们的输出是这手牌是否是赢牌。 要使一手牌成为赢手,必须可以按照以下规则将其数字分组:

  1. 每组 3 个必须是相同的数字或顺子(111 或 123)
  2. 我们只能有一对相同的数字(22 可以,但 45 不行)

例如:

[1,1,2,3,4,5,5]: True
[1,6]: False
[1,6,8,8]: True

我使用回溯技术为问题编写了以下解决方案:

注意:忽略所有出现的 seen 它是我下面问题第二部分的记忆的一部分。

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,seen):
        return True
          
    valid,new_hand = take_straight(hand)
    if valid:
      if is_winning_hand_step(new_hand,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

现在我试图找出该问题的时间复杂度是多少。 让我们假设输入已经为我们排序,所以将它的 O(N log N) 放在一边。

我的猜测是,因为在每一步中,我都有可能分成 3 个分支,所以复杂度是 O(3^N),其中 N 应该是输入数组的长度。在我们的例子中,它总是 14 个长度的数组,但我说的是一般情况。我说的对吗?

在下一步中,我在我的解决方案中添加了记忆。关于时间复杂度,我们现在能说什么?多亏了记忆,我避免了一次又一次地解决相同的子问题,所以这使它成为 O(N) 解决方案吗?

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。