Recentemente, deparei-me com uma tarefa clássica de entrevistas: procurar o número máximo de pontos em uma linha reta (em um plano, coordenadas inteiras). A ideia de pesquisa exaustiva veio imediatamente à minha mente, que tem óbvia complexidade de tempo em O (n ^ 2), mas me pareceu que deveria haver algo mais, pelo menos alguma alternativa em O (n * log (n)) . Depois de meia hora, até algo melhor foi encontrado!
Uma declaração mais detalhada do problema com exemplos de entrada e saída está em GeeksForGeeks e LeetCodeInicialmente, notei que você pode resolver facilmente o problema apenas para linhas horizontais ou verticais, adicionando o X / Y de cada ponto no dicionário. E qual é a diferença entre as outras linhas? Apenas uma ladeira? .. Mas é corrigível!
Assim, decidi que era possível percorrer toda a lista de pontos várias vezes girando-os. E a solução em O (n) é obtida! Embora com um grande coeficiente. Eu realmente espero não ter inventado uma bicicleta :)
Visualizado, parece algo como isto:
meu primeiro GIF caseiro, por favor, não repreenda :)
É interessante notar que a
implementação subsequente
da pesquisa exaustiva ocupou mais linhas de código.
O gráfico com medições do tempo de execução do meu algoritmo rotacional e a enumeração completa, dependendo do número de pontos, está no cabeçalho.
Aproximadamente 150 pontos mostram a vantagem da complexidade linear no tempo (com os coeficientes usados no código acima). Como resultado, esse algoritmo tem as seguintes desvantagens:
- A precisão não é absoluta.
- O tempo de execução em pequenos conjuntos de pontos é longo.
Em geral, isso é facilmente corrigido por uma seleção competente de coeficientes: para conjuntos simples, ROT_COUNT = 36 em vez de 2000 é suficiente, o que acelera o código mais de 50 vezes.
E essas vantagens:
- Trabalha calmamente com coordenadas fracionárias.
- A complexidade do tempo é linear, o que é perceptível em grandes conjuntos de dados.
Uma tabela com medidas
está disponível aqui . Todo o código fonte do projeto, com algoritmos e várias verificações,
está no GitHub .
Update Quero observar mais uma vez que esse algoritmo tem vantagens e desvantagens, não o advogo como um substituto ideal para força bruta, acabei de descrever uma alternativa possível interessante, que em alguns casos pode ser mais apropriada.