【问题标题】:Why my 2nd method is slower than my 1st method?为什么我的第二种方法比我的第一种方法慢?
【发布时间】:2017-06-10 03:58:17
【问题描述】:

我在做 leetcode 问题No. 387. First Unique Character in a String。给定一个字符串,找到其中的第一个非重复字符并返回它的索引。如果不存在,则返回 -1。

例子:

s = "leetcode"
return 0.

s = "loveleetcode",
return 2.

我写了2个算法:

方法一

def firstUniqChar(s):
    d = {}
    L = len(s)
    for i in range(L):
        if s[i] not in d:
            d[s[i]] = [i]
        else:
            d[s[i]].append(i)
    M = L
    for k in d:
        if len(d[k])==1:
            if d[k][0]<M:
                M = d[k][0]
    if M<L:
        return M
    else:
        return -1

这非常直观,即首先通过循环遍历s 中的所有字符来创建一个计数字典(这也可以使用collections.Counter 中的一行来完成),然后进行第二次循环,仅检查那些value 是长度为 1 的列表。我认为当我做了 2 个循环时,它必须有一些冗余计算。所以我写了第二个算法,我认为它比第一个更好,但是在 leetcode 平台上,第二个比第一个运行得慢得多,我不知道为什么。

方法二

def firstUniqChar(s):
    d = {}
    L = len(s)
    A = []
    for i in range(L):
        if s[i] not in d:
            d[s[i]] = i
            A.append(i)
        else:
            try:
                A.remove(d[s[i]])
            except:
                pass

    if len(A)==0:
       return -1
    else:
       return A[0]

第二个只为s中的所有字符循环一次

【问题讨论】:

  • A.remove(...)A 上循环。重复这样做很昂贵。
  • @user2357112 谢谢!

标签: python algorithm time-complexity


【解决方案1】:

您的第一个解决方案是O(n),但您的第二个解决方案是O(n^2),因为方法A.remove 正在循环A 的元素。

【讨论】:

  • 谢谢!我确实意识到了
【解决方案2】:

正如其他人所说 - 使用 list.remove 非常昂贵...您使用 collections.Counter 是个好主意。

您需要扫描字符串一次 以查找唯一性。那么可能更好的是再次顺序扫描它并获取第一个唯一的索引 - 这使得您的潜在代码:

from collections import Counter

s = "loveleetcode"

# Build a set of unique values
unique = {ch for ch, freq in Counter(s).items() if freq == 1}
# re-iterate over the string until we first find a unique value or 
# not - default to -1 if none found
first_index = next((ix for ix, ch in enumerate(s) if ch in unique), -1)
# 2

【讨论】:

  • 我很好奇这个问题,有没有比 O(n) 更快的算法?我想不会吧?
  • @ftxx 除非有一些保证数据在呈现时总是连续的,例如 `aaabbcccddefff',否则不 - 你必须至少扫描一次完整的东西
  • 话虽如此 - 您可能会调整后面的部分以不重新迭代原始字符串,如果它很长并且包含很多重复值,这可能是值得的......但没有... 小于 O(N) 是不可能的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-05-02
  • 2013-05-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-06-27
  • 2020-12-17
相关资源
最近更新 更多