Fiz essa pergunta em uma entrevista de emprego e gostaria de saber como os outros a resolveriam. Eu me sinto mais à vontade com Java, mas soluções em outros idiomas são bem-vindas.
Dada uma matriz de números,
nums
retorne uma matriz de númerosproducts
, ondeproducts[i]
é o produto de todosnums[j], j != i
.Input : [1, 2, 3, 4, 5] Output: [(2*3*4*5), (1*3*4*5), (1*2*4*5), (1*2*3*5), (1*2*3*4)] = [120, 60, 40, 30, 24]
Você deve fazer isso
O(N)
sem usar a divisão.
[interview-questions]
tag procurando por ela. Você tem um link se o encontrou?Respostas:
Uma explicação do método de poligenelubricants é: O truque é construir as matrizes (no caso de 4 elementos)
Ambos podem ser feitos em O (n) iniciando nas bordas esquerda e direita, respectivamente.
Multiplicar as duas matrizes elemento por elemento fornece o resultado necessário
Meu código ficaria assim:
Se você também precisa ser O (1) no espaço, pode fazê-lo (que é menos claro no IMHO)
fonte
v_i=0
que a única entrada diferente de zero no resultado seja o i-ésimo elemento. No entanto eu suspeito que a adição de um passe para detectar e contar os elementos de zero prejudicaria a clareza da solução, e provavelmente não fazer qualquer ganho de desempenho real na maioria dos casos ..Aqui está uma pequena função recursiva (em C ++) para fazer a modificação no local. No entanto, requer O (n) espaço extra (na pilha). Assumindo que a matriz esteja em a e N mantenha o comprimento da matriz, temos
fonte
num[N-1]
; depois, no caminho de volta, calcula a segunda parte da multiplicação que é usada para modificar a matriz numérica.Aqui está a minha tentativa de resolvê-lo em Java. Desculpas pela formatação não padrão, mas o código tem muita duplicação, e é o melhor que posso fazer para torná-lo legível.
Os invariantes de loop são
pi = nums[0] * nums[1] *.. nums[i-1]
epj = nums[N-1] * nums[N-2] *.. nums[j+1]
. Ai
parte da esquerda é a lógica do "prefixo" e aj
parte da direita é a lógica do "sufixo".Uma linha recursiva
Jasmeet deu uma (linda!) Solução recursiva; Eu o transformei neste (hediondo!) Java de uma linha. Ele realiza modificações no local , com
O(N)
espaço temporário na pilha.fonte
Traduzindo a solução de Michael Anderson para Haskell:
fonte
Contornando furtivamente a regra "sem divisões":
fonte
Aqui está, solução simples e limpa com complexidade O (N):
fonte
C ++, O (n):
fonte
Em)
fonte
Aqui está minha solução em C ++ moderno. Faz uso
std::transform
e é muito fácil de lembrar.Código online (caixa de varinha).
fonte
Este é O (n ^ 2), mas f # é muuuuito bonito:
fonte
Pré-calcule o produto dos números à esquerda e à direita de cada elemento. Para cada elemento, o valor desejado é o produto de seus produtos neigbors.
Resultado:
(ATUALIZAÇÃO: agora eu olho mais de perto, isso usa o mesmo método de Michael Anderson, Daniel Migowski e poligenelubrificantes acima)
fonte
Complicado:
Use o seguinte:
Sim, tenho certeza de que perdi algum i-1 em vez de i, mas é esse o caminho para resolvê-lo.
fonte
Também existe uma solução não ótima de O (N ^ (3/2)) . É bastante interessante, no entanto.
Primeiro pré-processe cada multiplicação parcial de tamanho N ^ 0,5 (isso é feito com complexidade de tempo O (N)). Em seguida, o cálculo para os outros valores múltiplos de cada número pode ser feito em 2 * O (N ^ 0,5) tempo (por quê? Porque você só precisa multiplicar os últimos elementos de outros números ((N ^ 0,5) - 1)), e multiplique o resultado por ((N ^ 0,5) - 1) números que pertencem ao grupo do número atual). Fazendo isso para cada número, pode-se obter o tempo O (N ^ (3/2)).
Exemplo:
4 6 7 2 3 1 9 5 8
resultados parciais: 4 * 6 * 7 = 168 2 * 3 * 1 = 6 9 * 5 * 8 = 360
Para calcular o valor de 3, é necessário multiplicar os valores dos outros grupos 168 * 360 e depois com 2 * 1.
fonte
Esta solução surgiu e achei tão claro o que você acha !?
fonte
arr = [1, 2, 3, 4, 5] prod = [] productify (arr, prod, 0) print prod
fonte
Para estar completo aqui, está o código no Scala:
Isso imprimirá o seguinte:
O programa filtrará o elem atual (_! = Elem); e multiplique a nova lista com o método reduzemLeft. Eu acho que isso será O (n) se você usar o scala view ou o Iterator para avaliação preguiçosa.
fonte
Com base na resposta Billz - desculpe, não posso comentar, mas aqui está uma versão do scala que lida corretamente com itens duplicados na lista e provavelmente é O (n):
retorna:
fonte
Adicionando minha solução javascript aqui, pois não encontrei ninguém sugerindo isso. O que é dividir, exceto contar o número de vezes que você pode extrair um número de outro número? Passei por calcular o produto de toda a matriz e, em seguida, iterar sobre cada elemento e subtrair o elemento atual até zero:
fonte
Estou acostumado a c #:
fonte
Podemos excluir o
nums[j]
(wherej != i
) da lista primeiro e depois obter o produto do resto; O seguinte é umpython way
para resolver este quebra-cabeça:fonte
Bem, essa solução pode ser considerada a do C / C ++. Digamos que temos uma matriz "a" contendo n elementos como um [n], então o pseudo-código seria o seguinte.
fonte
Mais uma solução, usando a divisão. com duas vezes a travessia. Multiplique todos os elementos e comece a dividi-lo por cada elemento.
fonte
fonte
Aqui está o meu código:
fonte
Aqui está um exemplo um pouco funcional, usando C #:
Não estou totalmente certo de que seja O (n), devido à semi-recursão dos Funcs criados, mas meus testes parecem indicar que é O (n) a tempo.
fonte
// Esta é a solução recursiva em Java // Chamada como a seguir do produto principal (a, 1,0);
fonte
Uma solução elegante com tempo de execução O (n):
Crie uma matriz final "resultado", para um elemento i,
fonte
fonte
Aqui está outro conceito simples que resolve o problema
O(N)
.fonte
Eu tenho uma solução com complexidade de
O(n)
espaço eO(n^2)
tempo fornecida abaixo,fonte