【问题标题】:How can I efficiently count the number of occurrences of a given character within certain range of a string?如何有效地计算给定字符在字符串的特定范围内出现的次数?
【发布时间】:2017-04-18 08:08:01
【问题描述】:

给定一个未排序的字符串,例如“古戈尔”。我想在范围内找到字符“o”的出现次数:[1, 3)。所以,在这种情况下,答案是 1。

但是,我的方法复杂度为 O(N^2)。我的方法的问题是复制数组需要 O(N) 时间。因此,我一直在寻找另一种更有效的方法。空间复杂度对我来说并不重要。因为我是学习字符串处理算法的,所以这个算法最好自己实现。

任何帮助将不胜感激。

我的方法。

tmp = [0] * 26  # 26 alphabet
occurrences_table = []
tmp[ord(a_string[0])] += 1
occurrences_table.append(tmp)
for i in range(1, len(a_string)):
    temp = occurrences_table[i - 1]
    temp[ord(a_string[i])] += 1
    occurrences_table.append(temp)

【问题讨论】:

  • 检查collections.counter。您可以使用slicing 处理特定范围的字符串。
  • @umutto。但这就像我正在学习一些字符串处理算法。所以我想自己实现这个算法。
  • @kevinnnluo - 你真的应该在你原来的问题中提到这种克制。
  • @Christian König。是的,我的错。我已经编辑过了。

标签: python arrays string algorithm


【解决方案1】:

由于您不想使用counter 并想自己实现它,您的代码可以通过使用字典来整理和加速。

a_string = "googol"
my_counter = {}
for c in a_string[:2]:
    my_counter[c] = my_counter.get(c, 0) + 1

这会给你:

{'o': 1, 'g': 1}

为了进一步解释,a_string[:2] 获取字符串中索引 2 之前的字符 ('google'[:2] = 'go'),for c in a_string[:2]: 循环遍历这两个字符。

在下一行中,my_counter.get(c, 0) + 1 尝试获取键“c”(字符串中的单个字符)的字典值,如果存在则返回其值,如果不存在则返回 0,并且无论哪种方式都会添加递增的值返回字典。


编辑:

由于 dictionary.get() 的复杂度是恒定的,因此由于 for 循环,复杂度应该只是 O(n)。

我已经测量了它,对于像你这样的非常小的字符串,这种方法比 Collections.Counter 快 8-10 倍,但对于非常大的字符串,它慢 2-3 倍。

【讨论】:

    【解决方案2】:

    你可以使用Counter:

    from collections import Counter
    a_string = "googol"
    occurrences = Counter(a_string[0:2])
    

    导致

    Counter({'o': 1, 'g': 1})
    

    请注意,数组切片适用于字符串。

    【讨论】:

      【解决方案3】:

      如果你可以使用标准库:

      >>> from itertools import islice
      >>> from collections import Counter
      >>> Counter(islice('googol', 1, 3))
      Counter({'o': 2})
      >>> Counter(islice('googol', 0, 2))
      Counter({'g': 1, 'o': 1})
      

      islice 避免使用临时列表。)

      如果您想手动操作:

      >>> s = 'googol'
      >>> counter = dict()
      >>> for i in range(0, 2):
      ...     if s[i] not in counter:
      ...         counter[s[i]] = 1
      ...     else:
      ...         counter[s[i]] += 1
      ... 
      >>> counter
      {'g': 1, 'o': 1}
      

      重点是:使用dict

      【讨论】:

      • 我认为他的range [1, 3)-notation 从位置 1 开始计数字符直到并排除位置 3 - 在 python 中非常有效 [0:2]。
      • 感谢您的回答。因为范围是[1, 3),子串是“go”,只有一个“o”。但是就像我在学习字符串处理算法一样,所以我想自己实现。
      • 是的,当我看到你回答时我意识到了;)
      • @kevinnnluo python中的索引从0开始,这就是我困惑的原因。
      猜你喜欢
      • 2020-11-09
      • 2019-12-10
      • 1970-01-01
      • 2011-07-08
      • 2015-08-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多