Leetcode0479. Produto Palindrômico Máximo (difícil)

contente

1. Descrição do tópico

2. Análise de resolução de problemas

2.1 A construção de números palíndromos

2.2 Determine se existe um fator de n dígitos 

3. Implementação do código


1. Descrição do tópico

Dado um inteiro n, retorne no maior . Como a resposta pode ser muito grande, retorne- 1337 a restante .

Exemplo 1:

Entrada: n = 2
 Saída: 987
 Explicação: 99 x 91 = 9009, 9009 % 1337 = 987

Exemplo 2:

Entrada: n = 1
 Saída: 9

dica:

  • 1 <= n <= 8

2. Análise de resolução de problemas

        A violência simples definitivamente não é suficiente, e algumas análises matemáticas são necessárias para simplificar o problema.

        Considere o intervalo do produto de dois números de n dígitos.

        O valor mínimo é 10^{n-1} * 10^{n-1} = 10^{2n-2}2n-1 dígitos

        O valor máximo (10^n-1)^2 = 10^{2n} - 2\cdot 10^n + 1é de 2n dígitos

        A maneira intuitiva de fazer isso é pesquisar números palindrômicos com fatores de n dígitos nesse intervalo, de grande a pequeno:

  •         (1) Primeiro encontre o número de palíndromos neste intervalo (de grande a pequeno)
  •         (2) Determine se o palíndromo tem um fator de n dígitos

2.1 A construção de números palíndromos

        Como o número do palíndromo é simétrico, a construção e a travessia do palíndromo podem ser realizadas usando esta propriedade simétrica. No entanto, é necessário distinguir entre número par e ímpar de dígitos (como mencionado acima, o produto de dois números de n dígitos é no máximo 2n dígitos, que é um número par, e um mínimo de 2n-1 dígitos, que é um numero impar).

        Para 2n dígitos, a primeira metade (metade esquerda) é obtida percorrendo os n dígitos de grande para pequeno, e então a segunda metade é obtida na ordem inversa, e as duas são concatenadas para obter um palíndromo de 2n bits. A escolha de percorrer a primeira metade em vez da segunda metade é por causa da especialidade do maior número de dígitos (não pode ser 0). O total é um 10^{n} - 10^{n-1}número.

        Para 2n-1 dígitos, a primeira metade (metade esquerda) é obtida percorrendo os n-1 dígitos de grande para pequeno, e então a segunda metade é obtida na ordem inversa, e qualquer número é inserido no meio, ou seja, um (2n-1) bits do palíndromo. O total também é um 10 \cdot (10^{n-1} - 10^{n-2}) = 10^n - 10^{n-1}número.

2.2 Determine se existe um fator de n dígitos 

        O passo (2) não é equivalente à fatoração de primos, porque a questão não requer o produto de dois números primos. Na fatoração primária de um palíndromo, o produto de um subconjunto pode ser n dígitos (o produto do subconjunto complementar correspondente também deve ser n dígitos).

        Você pode 10^n - 1percorrer um por um para verificar se o número palíndromo p construído acima é divisível, e o limite inferior da travessia sqrt (p)pode ser (este é o mesmo que o princípio de que você só precisa julgar de pequeno a grande ao julgar números primos sqrt (p), e não será repetido aqui).

3. Implementação do código

import time
class Solution:
    def largestPalindrome(self, n: int) -> int:
        if n == 1:
            return 9        
        
        # case1: 2n digits number
        upper = 10 ** n - 1
        for left in range(upper, upper // 10, -1): 
            # The left(upper) half of the palindrome
            x = str(left)
            p = int(x + x[::-1])
            
            x = upper
            # while x*x >= p and x >= 10 ** (n-1):
            while x*x >= p:
                if p%x == 0:
                    print('The answer is 2n digits number')
                    return p%1337
                x -= 1
        
        # case2: 2n-1 digits number
        upper1 = 10 ** (n-1) - 1
        for left in range(upper1, upper1 // 10, -1): 
            # The left(upper) half of the palindrome
            x = str(left)
            for k in range(10):
                p = int(x + str(k) + x[::-1])
                x = upper
                # while x*x >= p and x >= 10 ** (n-1):
                while x*x >= p:
                    if p%x == 0:
                        print('The answer is (2n-1) digits number')
                        return p%1337
                    x -= 1                            
            

if __name__ == "__main__":
    
    sln = Solution()
    
    for k in range(1,9):
        tstart = time.time()
        ans = sln.largestPalindrome(k)
        tstop  = time.time()
        print('k={0}, ans={1}, tcost={2:4.2f}'.format(k,ans,tstop-tstart))

        Tempo de execução: 2964 ms, superando 19,74% dos usuários em todos os commits do Python3

        Consumo de memória: 15,1 MB, supera 6,58% dos usuários em todos os commits do Python3

        No código acima, se a condição "while x*x >= p and x >= 10 ** (n-1):" for usada, ela é mais rigorosa, mas o tempo é mais que o dobro, e o resultado é não diferente. Portanto, seria perfeito se pudesse ser provado matematicamente que a condição "x >= 10 ** (n-1)" não é necessária.

        Além disso, os resultados vistos de acordo com as informações de impressão mostram que os resultados finais são todos 2n dígitos e não há caso de 2n-1 dígitos. Mas se não puder ser provado matematicamente, não poderá ser salvo na implementação do código.

        De volta ao diretório principal: Notas diárias de solução de problemas do Leetcode (atualização dinâmica...)

Acho que você gosta

Origin blog.csdn.net/chenxy_bwave/article/details/124207585
Recomendado
Clasificación