Isso foi solicitado a mim em uma entrevista e esta é a solução que forneci:
public static int[] merge(int[] a, int[] b) {
int[] answer = new int[a.length + b.length];
int i = 0, j = 0, k = 0;
while (i < a.length && j < b.length)
{
if (a[i] < b[j])
{
answer[k] = a[i];
i++;
}
else
{
answer[k] = b[j];
j++;
}
k++;
}
while (i < a.length)
{
answer[k] = a[i];
i++;
k++;
}
while (j < b.length)
{
answer[k] = b[j];
j++;
k++;
}
return answer;
}
Existe uma maneira mais eficiente de fazer isso?
Editar: métodos de comprimento corrigidos.
while (i < a.length && j < b.length) answer[k++] = a[i] < b[j] ? a[i++] : b[j++];
Especificação da linguagem Java: Operador condicional? : .Respostas:
Uma pequena melhoria, mas após o loop principal, você pode
System.arraycopy
copiar a cauda de qualquer matriz de entrada quando chegar ao final da outra. Isso não altera asO(n)
características de desempenho da sua solução.fonte
É um pouco mais compacto, mas exatamente o mesmo!
fonte
Estou surpreso que ninguém tenha mencionado essa implementação muito mais interessante, eficiente e compacta:
Pontos de interesse
System.arraycopy
vencerão, porque internamente isso pode ser feito com uma única instrução de montagem x86.a[i] >= b[j]
vez dea[i] > b[j]
. Isso garante "estabilidade", definida como quando os elementos de aeb são iguais, queremos elementos de a antes de b.fonte
j < 0
,b
já está esgotado, por isso, manter-se adicionar os restantesa
elementos daanswer
gamaQuaisquer melhorias que poderiam ser feitas seriam micro-otimizações, o algoritmo geral está correto.
fonte
System.arrayCopy()
é estupidamente rápido, pois utilizamemcpy
chamadas otimizadas para CPU . Portanto, há escopo para melhorar o desempenho, copiando pedaços. Também há escopo para a pesquisa binária dos limites.Essa solução também é muito semelhante a outras postagens, exceto pelo uso de System.arrayCopy para copiar os elementos restantes da matriz.
fonte
Aqui está a função atualizada. Ele remove duplicatas, espero que alguém ache isso útil:
fonte
Isso pode ser feito em 4 instruções, como abaixo
fonte
sort
função não pode se usar como um método de classificação. Isso seria regressão infinita em vez de recursão. A outra premissa também é que merge_array é a função que implementa a classificação. Portanto, essa resposta é inutilizável no contexto mais provável.Eu tive que escrever em javascript, aqui está:
fonte
As coleções do Apache suportam o método collate desde a versão 4; você pode fazer isso usando o
collate
método em:Aqui citação de javadoc:
Não reinvente a roda! Referência do documento: http://commons.apache.org/proper/commons-collections/apidocs/org/apache/commons/collections4/CollectionUtils.html
fonte
Integração do GallopSearch: O (log (n) * log (i)) vez de O (n)
Fui em frente e implementei a sugestão de barba cinzenta nos comentários. Principalmente porque eu precisava de uma versão de missão crítica altamente eficiente desse código.
Essa deve ser a maneira mais eficiente de fazer isso, com complexidade de tempo de O (log (n) * log (i)) vez de O (n). E, no pior dos casos, complexidade do tempo de O (n). Se suas matrizes forem desajeitadas e tiverem longas cadeias de valores juntas, isso diminuirá qualquer outra maneira de fazê-lo; caso contrário, será apenas melhor que elas.
Ele possui dois valores de leitura nas extremidades da matriz mesclada e o valor de gravação na matriz de resultados. Depois de descobrir qual é o valor final menor, ele faz uma busca galopante nessa matriz. 1, 2, 4, 8, 16, 32, etc. Quando encontra o intervalo em que o valor de leitura da outra matriz é maior. Ele pesquisa binário nesse intervalo (corta o intervalo pela metade, pesquisa pela metade correta, repita até o valor único). Em seguida, o array copia esses valores na posição de gravação. Lembre-se de que a cópia é movida por necessidade, de modo que não possa sobrescrever os mesmos valores da matriz de leitura (o que significa que a matriz de gravação e a matriz de leitura podem ser as mesmas). Em seguida, ele executa a mesma operação para a outra matriz, que agora é conhecida como menor que o novo valor de leitura da outra matriz.
Essa deve ser a maneira mais eficiente de fazer isso.
Algumas respostas tiveram uma capacidade de remoção duplicada. Isso exigirá um algoritmo O (n) porque você deve realmente comparar cada item. Então, aqui está um exemplo independente, a ser aplicado após o fato. Você não pode galopar várias entradas até o fim, se precisar olhar para todas elas, embora possa galopar pelas duplicatas, se tiver muitas delas.
Atualização: resposta anterior, código não horrível, mas claramente inferior ao acima.
Outra hiper otimização desnecessária. Ele não apenas chama arraycopy para os bits finais, mas também para o começo. Processando qualquer não sobreposição introdutória em O (log (n)) por um binarySearch nos dados. O (log (n) + n) é O (n) e, em alguns casos, o efeito será bastante pronunciado, especialmente em situações em que não há sobreposição entre as matrizes mescladas.
fonte
That is totally what the implemented Arrays.sort does
( Isso : da primeira revisão de sua resposta - ou - do meu comentário de 19 de fevereiro?) - também não pode ser encontrado no JDK 8 da Sunsoft: a qual implementaçãoArrays.sort
você está se referindo?Aqui está um formulário abreviado escrito em javascript:
fonte
fonte
a[mid+1 .. hi]
paraaux
para?Acho que a introdução da lista de pulos para uma matriz classificada maior pode reduzir o número de comparações e acelerar o processo de cópia na terceira matriz. Isso pode ser bom se a matriz for muito grande.
fonte
fonte
fonte
for (int i, j, k = i = j = 0 ; k < c.length ; ) c[k++] = b.length <= j || i < a.length && a[i] < b[j] ? a[i++] : b[j++];
. Qual é a diferença da resposta de Andrew de 2014 ?O algoritmo pode ser aprimorado de várias maneiras. Por exemplo, é razoável verificar, se
a[m-1]<b[0]
oub[n-1]<a[0]
. Em qualquer um desses casos, não há necessidade de fazer mais comparações. O algoritmo pode apenas copiar as matrizes de origem na resultante na ordem correta.Aprimoramentos mais complicados podem incluir a pesquisa de peças intercaladas e executar o algoritmo de mesclagem apenas para elas. Isso pode economizar muito tempo, quando os tamanhos das matrizes mescladas diferem em dezenas de vezes.
fonte
Esse problema está relacionado ao algoritmo mergesort, no qual duas sub-matrizes classificadas são combinadas em uma única sub-matriz classificada. O CLRS livro do fornece um exemplo do algoritmo e limpa a necessidade de verificar se o fim foi alcançado adicionando um valor sentinela (algo que se compara e "maior que qualquer outro valor") ao final de cada matriz.
Eu escrevi isso em Python, mas deve ser traduzido também para Java:
fonte
Você pode usar 2 threads para preencher a matriz resultante, uma de frente e outra de trás.
Isso pode funcionar sem qualquer sincronização no caso de números, por exemplo, se cada thread inserir metade dos valores.
fonte
fonte
fonte
fonte
Minha linguagem de programação favorita é JavaScript
fonte
Talvez use System.arraycopy
fonte
A saída é:
1, 2, 3, 4, 5, 6, 8, 9, 10, 100, 999, 1001,
fonte
arr2
nãoind2
, mastemp
.Você pode usar operadores ternários para tornar o código um pouco mais compacto
fonte
Apenas um pouco diferente da solução original
fonte
Para marcar duas matrizes ordenadas em complexidade de tempo O (m + n), use a abordagem abaixo apenas com um loop. m e n é o comprimento da primeira matriz e da segunda matriz.
fonte
fonte
Como a pergunta não assume nenhum idioma específico. Aqui está a solução em Python. Supondo que as matrizes já estejam classificadas.
Abordagem 1 - usando matrizes numpy: import numpy
Abordagem 2 - Usando a lista, assumindo que as listas sejam classificadas.
fonte
Since the question doesn't assume any specific language
de 2011/5/11/19: 43, está marcado com java ..sort()
éO(n log n)
na melhor das hipótesesAqui está a minha implementação java que remove duplicado.
fonte