Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/348.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 可能具有最佳时间复杂度的字母汤问题_Python_Algorithm_Data Structures - Fatal编程技术网

Python 可能具有最佳时间复杂度的字母汤问题

Python 可能具有最佳时间复杂度的字母汤问题,python,algorithm,data-structures,Python,Algorithm,Data Structures,作为我的数据结构课程练习,我得到了以下问题(字母汤) 我在O(m+s)中解决了这个问题,其中m是消息的长度,s是soup的长度(我刚刚从soup中创建了一个表,并决定是否可以使用该表创建消息) 但是似乎给定的GITHUB在O(mLogm)中解决了它,但是我认为他/她的解决方案在O(m*s)中,因为他/她没有考虑Python的操作符在O中(列表的长度)。 顺便问一下,有人能不能提示一下,这有可能以更好的时间复杂度解决这个问题?(问题说明这碗汤可能非常大)我认为你不能在这个问题上走到线性以下,因为

作为我的数据结构课程练习,我得到了以下问题(字母汤)

我在O(m+s)中解决了这个问题,其中m是消息的长度,s是soup的长度(我刚刚从soup中创建了一个表,并决定是否可以使用该表创建消息)

但是似乎给定的GITHUB在O(mLogm)中解决了它,但是我认为他/她的解决方案在O(m*s)中,因为他/她没有考虑Python的操作符在O中(列表的长度)。


顺便问一下,有人能不能提示一下,这有可能以更好的时间复杂度解决这个问题?(问题说明这碗汤可能非常大)

我认为你不能在这个问题上走到线性以下,因为不分析字母汤就无法检查字母是否属于字母汤,而且你显然必须分析你的信息

但是,您的解决方案平均而言是线性的,因为哈希映射平均而言具有恒定的复杂性。因此,最坏情况的复杂性更像O(s^2+s.m)

例如,您可以使用自己的数据结构(不依赖散列而是二叉树)对其进行改进,以实现O(s.log(s)+m.log(s))的最坏情况复杂性

编辑:您还可以利用字符仅为ASCII字符这一事实

def checkBowl(message, soup):                                                                                                                                                                            
  d = [0 for i in range(128)]
              
  # O(S)      
  for c in soup:
    d[ord(c)] +=1
              
  # O(m)      
  for c in message:
    if(d[ord(c)] == 0):
      return False
    else:     
      d[ord(c)] -= 1
               
  # So the overall time complexity is O(m+s)
  return True 

我不认为你能在这个问题上走到线性以下,因为不分析一个字母是否属于字母汤是不可能的,而且你显然必须分析你的信息

但是,您的解决方案平均而言是线性的,因为哈希映射平均而言具有恒定的复杂性。因此,最坏情况的复杂性更像O(s^2+s.m)

例如,您可以使用自己的数据结构(不依赖散列而是二叉树)对其进行改进,以实现O(s.log(s)+m.log(s))的最坏情况复杂性

编辑:您还可以利用字符仅为ASCII字符这一事实

def checkBowl(message, soup):                                                                                                                                                                            
  d = [0 for i in range(128)]
              
  # O(S)      
  for c in soup:
    d[ord(c)] +=1
              
  # O(m)      
  for c in message:
    if(d[ord(c)] == 0):
      return False
    else:     
      d[ord(c)] -= 1
               
  # So the overall time complexity is O(m+s)
  return True 

如您所述,对于消息中的每个字母,链接算法都会在soup上迭代以查找字母。如果找到了字母,则会将其从汤中取出。因此,时间复杂度为
O(m*S)

您的算法是
O(m+S)
,因为您只在汤上迭代一次。所以你的解决方案更好

但是如果汤很大怎么办?来一份无限汤怎么样?如果soup是一个无限生成器,那么即使soup的第一个字母是消息本身,您也永远无法完成词典的构建

这就引出了一个想法:为什么不反复检查汤的字母,直到您得到消息的字母?在这种情况下,您将阅读信件,直到您能够编写邮件,并在邮件完成后立即停止:

import collections

def check_bowl2(message, soup):
    # O(m)
    message_letters = collections.Counter(message)

    # O(S)
    for c in soup:
        if c not in message_letters: # we don't need `c`
            pass
        elif message_letters[c] == 1:
            del message_letters[c] # we won't need `c` anymore
            if not message_letters: # we found all letters
                return True
        else: # we still need `c`, but one less time
            message_letters[c] -= 1

    return False
时间复杂度仍然是
O(m+S)
,但是空间复杂度降低了:
O(m)
O(S)
。当然,如果您正在同一个汤中查找许多消息,那么构建dict仍然是最佳选择


我认为你不会找到比O(S)更快的算法:在最坏的情况下(没有消息),你必须至少在整个汤中迭代一次。

如你所述,链接算法会对消息中的每个字母在汤中迭代以查找字母。如果找到了字母,则会将其从汤中取出。因此,时间复杂度为
O(m*S)

您的算法是
O(m+S)
,因为您只在汤上迭代一次。所以你的解决方案更好

但是如果汤很大怎么办?来一份无限汤怎么样?如果soup是一个无限生成器,那么即使soup的第一个字母是消息本身,您也永远无法完成词典的构建

这就引出了一个想法:为什么不反复检查汤的字母,直到您得到消息的字母?在这种情况下,您将阅读信件,直到您能够编写邮件,并在邮件完成后立即停止:

import collections

def check_bowl2(message, soup):
    # O(m)
    message_letters = collections.Counter(message)

    # O(S)
    for c in soup:
        if c not in message_letters: # we don't need `c`
            pass
        elif message_letters[c] == 1:
            del message_letters[c] # we won't need `c` anymore
            if not message_letters: # we found all letters
                return True
        else: # we still need `c`, but one less time
            message_letters[c] -= 1

    return False
时间复杂度仍然是
O(m+S)
,但是空间复杂度降低了:
O(m)
O(S)
。当然,如果您正在同一个汤中查找许多消息,那么构建dict仍然是最佳选择


我认为你不会找到比O(S)更快的算法:在最坏的情况下(没有消息),你必须在整个汤中至少迭代一次。

哦,对了。我完全忘记了哈希表在最坏情况下的复杂性是O(n)。谢谢:)但是通过使用堆这一完整的二叉树,顺序将是O(s.log(s)+m.log(m)),而不是O(s.log(s)+m.log(s))。我说得对吗?我的意思是你在答案的最后一行打错了,或者我误解了使用二叉树的解决方案。@Me。我在考虑一个解决方案,其中与当前解决方案的唯一区别是映射实现,使用树覆盖散列。你对解决方案的想法是什么?我会尽快去做possible@Me. 完成了,真的很好,对吧。我完全忘记了哈希表在最坏情况下的复杂性是O(n)。谢谢:)但是通过使用堆这一完整的二叉树,顺序将是O(s.log(s)+m.log(m)),而不是O(s.log(s)+m.log(s))。我说得对吗?我的意思是你在答案的最后一行打错了,或者我误解了使用二叉树的解决方案。@Me。我在考虑一个解决方案,其中与当前解决方案的唯一区别是映射实现,使用树覆盖散列。你对解决方案的想法是什么?我会尽快去做possible@Me. 完成了,真正的线性是的,正如我提到的,问题是“这可能是一碗包含许多字母的非常大的汤”,你的解决方案以某种方式解决了这个问题。但是在最坏的情况下访问字典O(1)还是O(n)?我的意思是,正如@TUI lover所提到的,最坏的情况是O(n),所以复杂度应该是O(mS),对吗?正如@TUI lover所说,对于字典来说,最坏的情况是
O(n)
。但是在您的例子中,您可以假设