【问题标题】:Python dictionary sorting Anagram of a string [duplicate]Python字典排序字符串的Anagram [重复]
【发布时间】:2018-02-16 14:41:40
【问题描述】:

我有以下问题,我找到了这个Permutation of string as substring of another,但这是使用 C++,我对应用 python 有点困惑。

给定两个字符串 s 和 t,判断 t 的某个字谜是否是 s 的子串。例如:如果 s = "udacity" 和 t = "ad",那么 函数返回 True。您的函数定义应如下所示: question1(s, t) 并返回布尔值 True 或 False。

所以我回答了这个问题,但他们希望我使用字典而不是排序字符串。审稿人这么说;

我们可以首先为 t 编译一个计数字典并检查每个 s 中可能的连续子串集。如果任何集合是 t 的字谜, 然后我们返回 True,否则返回 False。比较所有字符的计数 将可以在恒定时间内完成,因为数量有限 要检查的字符数。循环遍历所有可能的连续 子字符串将采用最坏情况 O(len(s))。因此,时间 该算法的复杂度为 O(len(s))。空间复杂度为 O(1) 虽然我们正在创建一个字典,因为我们最多可以有 26 个 字符,因此它是有界的。

请各位帮忙看看如何在我的解决方案中使用字典。

这是我的解决方案;

# Check if s1 and s2 are anagram to each other
def anagram_check(s1, s2):
    # sorted returns a new list and compare
    return sorted(s1) == sorted(s2)

# Check if anagram of t is a substring of s
def question1(s, t):
    for i in range(len(s) - len(t) + 1):
        if anagram_check(s[i: i+len(t)], t):
            return True
    return False

def main():
    print question1("udacity", "city")

if __name__ == '__main__':
    main()  

'''
Test Case 1: question1("udacity", "city") -- True
Test Case 2: question1("udacity", "ud") -- True
Test Case 3: question1("udacity", "ljljl") -- False
'''

感谢任何帮助。谢谢,

【问题讨论】:

  • 我投票决定将此问题作为离题结束,因为家庭作业是针对家庭的。
  • 审稿人所说的“我们可以先编译一个 t 的计数字典”是什么意思
  • @JoeIddon 创建一个包含 26 个条目的数组以保存 t 中的字母数,然后使用大小为 len(t) 的滑动窗口对 s 执行相同操作(因此计数不会改变或一个字母向前移动时减少而另一个增加),比较字典是 O(1),因为条目数是恒定的 (26)。
  • @maraca 帽子是有道理的,不得不考虑一下 lol - 字母表中有 26 个字母 :)
  • @maraca 在想,为什么还要将计数存储在dict 中,为什么不直接将它们与s 的计数进行比较?

标签: python algorithm sorting anagram


【解决方案1】:

一个纯python解决方案,用于获取一个对象,该对象对应于字母表中有多少个字符在一个字符串(t)中

使用函数chr(),您可以将int 转换为其对应的ascii 值,因此您可以轻松地将97 转换为123,并使用chr() 来获取字母表的该值。

所以如果你有一个字符串说:

t = "abracadabra"

然后你可以做一个for-loop 喜欢:

dt = {}
for c in range(97, 123):
   dt[chr(c)] = t.count(chr(c))

这适用于解决方案的这一部分,返回以下结果:

{'k': 0, 'v': 0, 'a': 5, 'z': 0, 'n': 0, 't': 0, 'm': 0, 'q': 0, 'f': 0, 'x': 0, 'e': 0, 'r': 2, 'b': 2, 'i': 0, 'l': 0, 'h': 0, 'c': 1, 'u': 0, 'j': 0, 'p': 0, 's': 0, 'y': 0, 'o': 0, 'd': 1, 'w': 0, 'g': 0}

不同的解决方案?

欢迎评论,但为什么需要存储在dict 中?使用count(),您能不能简单地将t 中每个字符的计数与s 中该字符的计数进行比较?如果t 中char 的计数大于s 中的计数,则返回False 否则True。

类似的东西:

def question1(s, t):
   for c in range(97, 123):
      if t.count(chr(c)) > s.count(chr(c)):
         return False
   return True

给出结果:

>>> question1("udacity", "city")
True
>>> question1("udacity", "ud")
True
>>> question1("udacity", "ljljl")
False

如果需要dict...

如果是,那么只需像上面那样创建两个并遍历每个键...

def question1(s, t):
   ds = {}
   dt = {}
   for c in range(97, 123):
      ds[chr(c)] = s.count(chr(c))
      dt[chr(c)] = t.count(chr(c))
   for c in range(97, 123):
      if dt[chr(c)] > ds[chr(c)]:
         return False
   return True

更新

以上回答只检查子序列而不是子串字谜。正如 maraca 在 cmets 中向我解释的那样,两者之间存在区别,您的示例说明了这一点。

使用滑动窗口的想法(通过对字符串进行切片),下面的代码应该适用于子字符串:

def question1(s, t):
   dt = {}
   for c in range(97, 123):
      dt[chr(c)] = t.count(chr(c))
   for i in range(len(s) - len(t) + 1):
      contains = True
      for c in range(97, 123):
         if dt[chr(c)] > s[i:i+len(t)].count(chr(c)):
            contains = False
            break
      if contains:
         return True
   return False

上面的代码适用于所有情况,并使用字典来正确加快计算速度:)

【讨论】:

  • 谢谢@Joe Iddon,我提供的解决方案已经奏效,但他们希望我使用 dict,这是项目的要求。
  • 谢谢@Joe Iddon,感谢您的帮助。
  • 这就是你要找的,够了吗? @cevadcevik
  • 是的@Joe Iddon,这就是我需要做的,顺便说一句抱歉回复晚了。谢谢,
  • 接受吗? :p
【解决方案2】:
import collections
print collections.Counter("google")

Counter({'o': 2, 'g': 2, 'e': 1, 'l': 1})

【讨论】:

  • 值得注意的是counter是dict的子类
  • 需要遍历子串dict并检查超串dict中的计数
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-05-14
  • 1970-01-01
  • 2014-06-19
  • 2023-02-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多