LeetCode Brushing Notes (Python3) - 3. A substring mais longa sem caracteres repetidos (dificuldade: média) (2021-05-11)

LeetCode brushing notes (Python3) - 3. A substring mais longa sem caracteres repetidos
(clique para ver o título)
(clique para ver a solução oficial)

Nota: A estrutura de dados usada na solução oficial desta questão é uma lista, que é significativamente mais lenta (já foi testada), portanto não é recomendada. Aqueles que estiverem interessados ​​em entender o uso da lista podem clicar no link para referência.

solução inicial

Como eu pessoalmente sei que ao pesquisar em Python, usar um dicionário (dict) é significativamente mais rápido do que usar uma lista (list), então eu uso diretamente um dicionário para auxiliar na programação.

# 时间复杂度:O(N) 空间复杂度:O(N)
class Solution:
    def lengthOfLongestSubstring(self, s: str) -> int:
        len_max, head, d = 0, 0, dict()
        for i, char in enumerate(s):
            if char in d:  # 该字符出现过
                len_max = max(len_max, i - head)
                new_head = d[char] + 1
                [d.pop(k) for k in s[head: new_head]]  # 剔除旧的无用字符
                head = new_head
            d[char] = i  # 将新字符加入字典
        return max(len_max, len(s) - head)

1. Habilidades exclusivas do Python: geração de listas

O gerador de lista pode gerar rapidamente uma lista com regras específicas e também pode executar rapidamente operações em lote com regras específicas.

[i**2 for i in range(4)]  # [0, 1, 4, 9]
[d.pop(k) for k in s]  # 把字典d中键值为s中字符的所有键值对从d中去除

2. O método de saída de pares chave-valor no dicionário no console

Essa técnica também pode ser usada para depuração de programas.

d = {
    
    2:'b', 1:'a', 3:'c'}
for j in d:
    print(j, d[j])
# result:
# 2 b
# 1 a
# 3 c

Solução ótima

Após referir-se aos poucos códigos com o menor tempo, e proceder para simplificar ainda mais, obtém-se a seguinte solução otimizada. Este algoritmo não é apenas mais curto, mas também mais rápido.

# 时间复杂度:O(N) 空间复杂度:O(N)
class Solution:
    def lengthOfLongestSubstring(self, s: str) -> int:
        len_max, start, d = 0, -1, dict()
        for i, char in enumerate(s):
            if char in d and d[char] > start:  # 该字符出现过 且 上次出现在当前子串中
                start = d[char]
            else:
                len_max = max(len_max, i - start)
            d[char] = i
        return len_max

O principal motivo da lentidão do algoritmo inicial é a necessidade de remover chaves antigas do dicionário. Por outro lado, o motivo pelo qual o algoritmo de otimização é mais rápido é que ele só precisa atualizar o valor da chave, não há necessidade de remover o valor da chave e a quantidade de operação é significativamente reduzida. O ponto central é que o algoritmo inicial é muito heurístico, enquanto a ideia do algoritmo do algoritmo otimizado é obviamente melhor.

おすすめ

転載: blog.csdn.net/AbaloneVH/article/details/116664260