Fui designado para um exercício na minha universidade. Levei para casa e tentei programar um algoritmo para resolvê-lo, era algo relacionado a gráficos, encontrando componentes conectados, eu acho.
Então eu fiz a coisa mais trivial que me veio à mente e depois mostrei ao meu professor. Após uma breve observação, ele percebeu que a complexidade do tempo de execução da minha solução era inviável e mostrou algo mais eficiente. E há uma tradição de programadores que não têm idéia do que é complexidade computacional (eu era um deles), então é um problema se um programador não tem idéia do que é complexidade computacional?
algorithms
algorithm-analysis
education
applied-theory
Billy Rubina
fonte
fonte
Respostas:
Sim, eu diria que conhecer algo sobre complexidade computacional é uma obrigação para qualquer programador sério. Contanto que você não esteja lidando com grandes conjuntos de dados, você não terá problemas com a complexidade, mas se quiser escrever um programa que lide com problemas sérios, será necessário.
No seu caso específico, seu exemplo de localização de componentes conectados pode ter funcionado para gráficos de até nós. No entanto, se você tentasse um gráfico com nós, o algoritmo de seu professor provavelmente conseguiria isso em 1 segundo, enquanto seu algoritmo teria (dependendo de quão ruim era a complexidade) levado 1 hora, 1 dia ou talvez até 1 eternidade.100.000100 100.000
Um erro bastante comum que os alunos cometem em nosso curso de algoritmos é iterar em uma matriz como esta:
Esse pode não ser o código mais bonito, mas em um programa complicado algo assim pode aparecer sem que o programador esteja ciente disso. Agora, qual é o problema com este programa?
Suponha que o executemos em um conjunto de dados de elementos. Comparado com o programa a seguir, o programa anterior executará mais lentamente.50.000100.000 50.000
Espero que você concorde que ter o conhecimento necessário para executar seu programa vezes mais rápido é provavelmente uma coisa importante para um programador. Compreender a diferença entre os dois programas requer algum conhecimento básico sobre a teoria da complexidade e algum conhecimento sobre os detalhes da linguagem em que você está programando.50.000
Na minha linguagem de pseudocódigo, "remover um elemento de uma matriz" desloca todos os elementos à direita do elemento, sendo removida uma posição da esquerda. Isso torna a remoção do último elemento uma operação , pois, para isso, precisamos interagir apenas com 1 elemento. A remoção do primeiro elemento é pois para remover o primeiro elemento, precisamos mudar todos os outros elementos uma posição para a esquerda também.O ( n ) n - 1O(1) O(n) n−1
Um exercício muito básico de complexidade é provar que o primeiro programa fará operações enquanto o segundo programa usa apenas operações. Se você conectar , verá que um programa é drasticamente mais eficiente que o outro.nn=100.00012n2 n n=100.000
Este é apenas um exemplo de brinquedo, mas já requer um entendimento básico da complexidade para diferenciar os dois programas. Se você estiver realmente tentando depurar / otimizar um programa mais complicado que possua esse erro, é necessário um entendimento ainda maior para encontrar onde está o erro. Porque um erro como remover um elemento de uma matriz dessa maneira pode ser muito bem oculto por abstrações no código.
Ter um bom entendimento da complexidade também ajuda na comparação de duas abordagens para resolver um problema. Suponha que você tenha apresentado duas abordagens diferentes para resolver o problema dos componentes conectados por conta própria: para decidir entre eles, seria muito útil se você pudesse (rapidamente) estimar sua complexidade e escolher a melhor.
fonte
"So long as you are not dealing with huge data sets you will be fine not knowing complexity"
Isso geralmente é verdade, mas nem sempre é assim. Por exemplo, umO(n!)
algoritmo não será viável, mesmo para conjuntos de dados relativamente pequenos. Se você usar umO(n!)
algoritmo em que você poderia ter usado,O(n^2)
seu programa levará 36.288 vezes mais para ser executado em um tamanho de dados 10 . Em um tamanho de dados de 20, você está olhando para 2,4 quintilhões de operações.Esta é uma refutação da resposta de Tom van der Zanden , que afirma que isso é essencial.
O problema é que, na maioria das vezes, 50.000 vezes mais devagar não é relevante (a menos que você trabalhe no Google, é claro).
Se a operação que você fizer demorar um microssegundo ou se o seu N nunca estiver acima de um certo limite (uma grande parte da codificação feita atualmente), NUNCA importará. Nesses casos, pensar em complexidade computacional fará com que você perca tempo (e provavelmente dinheiro).
A complexidade computacional é uma ferramenta para entender por que algo pode estar lento ou com uma escala ruim e como melhorá-lo, mas na maioria das vezes é um exagero total.
Sou programador profissional há mais de cinco anos e nunca encontrei a necessidade de pensar em complexidade computacional ao fazer um loop dentro de um loop O (M * N), porque sempre a operação é realmente rápida ou M e N são tão pequeno.
Há coisas muito mais importantes, geralmente usadas e mais difíceis de entender para qualquer pessoa que faça trabalhos de programação (encadeamento e criação de perfil são bons exemplos na área de desempenho).
Obviamente, há algumas coisas que você nunca poderá fazer sem entender a complexidade computacional (por exemplo: encontrar anagramas em um dicionário), mas na maioria das vezes você não precisa disso.
fonte
Desenvolvo software há cerca de trinta anos, trabalhando como contratada e como funcionário, e tenho tido muito sucesso nisso. Meu primeiro idioma era o BASIC, mas rapidamente aprendi a linguagem de máquina para obter uma velocidade decente da minha caixa de baixa potência. Passei muito tempo em criadores de perfil ao longo dos anos e aprendi muito sobre a produção rápida de código otimizado e eficiente em memória.
Independentemente de dizer, eu sou autodidata. Eu nunca encontrei a notação O até começar a entrevistar alguns anos atrás. Nunca aparece no meu trabalho profissional, EXCETO durante as entrevistas. Então, eu tive que aprender o básico apenas para lidar com essa questão em entrevistas.
Eu me sinto como o músico de jazz que não sabe ler partituras. Ainda posso jogar muito bem. Eu sei sobre hashtables (diabos, eu inventei hashtables antes de aprender que elas já haviam sido inventadas) e outras estruturas importantes de dados, e talvez até conheça alguns truques que eles não ensinam na escola. Mas acho que a verdade é que, se você quiser ter sucesso nessa profissão, precisará indie ou aprenderá as respostas para as perguntas que eles farão durante as entrevistas.
Aliás, recentemente entrevistei para uma função de desenvolvedor web front-end. Eles me fizeram uma pergunta em que a resposta exigia conhecimento de complexidade computacional e logaritmos. Consegui me lembrar de matemática suficiente de vinte anos atrás para respondê-la mais ou menos corretamente, mas foi um pouco chocante. Eu nunca tive que usar logaritmos em nenhum desenvolvimento de front-end.
Boa sorte para você!
fonte
A pergunta é bastante subjetiva, então acho que a resposta é que depende .
Não importa muito se você trabalha com pequenas quantidades de dados. Nesses casos, geralmente é bom usar o que quer que seja, por exemplo, a biblioteca padrão do seu idioma.
No entanto, quando você lida com grandes quantidades de dados ou, por algum outro motivo, insiste que seu programa é rápido, é necessário entender a complexidade computacional. Se não, como você sabe como um problema deve ser resolvido ou com que rapidez é possível resolvê-lo? Mas entender apenas a teoria não é suficiente para ser um bom programador. Para produzir código extremamente rápido, acredito, você também precisa entender como, por exemplo, sua máquina funciona (caches, layout de memória, conjunto de instruções) e o que o seu compilador faz (os compiladores fazem o melhor possível, mas não são perfeitos).
Em suma, acho que entender a complexidade claramente faz de você um programador melhor.
fonte
Certamente é um problema se alguém que está desenvolvendo algoritmos significativos não entende a complexidade do algoritmo. Os usuários de um algoritmo geralmente confiam em uma boa qualidade de implementação que possui boas características de desempenho. Embora a complexidade não seja a única colaboradora das características de desempenho de um algoritmo, é significativa. Alguém que não entende a complexidade do algoritmo tem menos probabilidade de desenvolver algoritmos com características úteis de desempenho.
É menos problemático para os usuários de um algoritmo, supondo que os algoritmos disponíveis sejam de boa qualidade. Isso é verdade para desenvolvedores que usam linguagens que possuem uma biblioteca padrão significativa e bem especificada - eles só precisam saber como escolher um algoritmo que atenda às necessidades. O problema ocorre quando existem vários algoritmos de algum tipo (digamos, classificação) disponíveis em uma biblioteca, porque a complexidade é frequentemente um dos critérios para escolher entre eles. Um desenvolvedor que não entende a complexidade não pode entender a base para escolher um algoritmo eficaz para a tarefa em questão.
Depois, há desenvolvedores que se concentram em (por falta de uma descrição melhor) preocupações não algorítmicas. Por exemplo, eles podem se concentrar no desenvolvimento de interfaces de usuário intuitivas. Esses desenvolvedores geralmente não precisam se preocupar com a complexidade do algoritmo, embora, novamente, possam contar com bibliotecas ou outro código sendo desenvolvido com alta qualidade.
fonte
Depende, mas não da quantidade de dados com que você está trabalhando, mas do tipo de trabalho que você faz, dos programas que você desenvolve.
Vamos chamar programador que não conhece a complexidade conceitual noobish programmer.
O programador noobish pode fazer:
O programador noobish não deve fazer:
Portanto, o programador noobish está bem, quando você quer apenas usar tecnologias. Então, quando se trata de desenvolvimento de novas soluções, tecnologias personalizadas, etc. Então é melhor contratar um programador não noobish.
No entanto, se a empresa não desenvolve novas tecnologias, apenas usa as já fabricadas. Seria desperdício de talento contratar programadores qualificados e talentosos. O mesmo se aplica: se você não deseja trabalhar em novas tecnologias e está bem em colocar idéias de clientes em projetos e programas usando estruturas já criadas, então é perda de tempo aprender algo que você nunca precisará, exceto se é seu hobby e você gosta de desafios lógicos.
fonte
Estou um pouco hesitante em escrever uma resposta aqui, mas desde que me encontrei falando sobre vários outros [alguns dos meus comentários foram movidos para o bate-papo], eis como eu o vejo ...
Existem níveis / graus de conhecimento em muitas coisas na computação (e, com esse termo, quero dizer mais ou menos a união da ciência da computação com a tecnologia da informação). A complexidade da computação certamente é um campo vasto (você sabe o que é OptP? Ou o que o teorema de Abiteboul-Vianu diz?) E também admite muita profundidade: a maioria das pessoas com um diploma em CS não pode produzir as provas de especialistas que são pesquisadas publicações em complexidade computacional.
O nível de conhecimento e habilidade / competência exigidos em tais assuntos depende muito do que se trabalha. A classificação O ( ) completamente sem noção às vezes é considerada uma das principais causas de programas lentos [citação necessário] , mas um artigo do SIGCSE de 2003 observou "A classificação por inserção é usada para classificar pequenas (sub) matrizes em bibliotecas padrão Java e C ++. " Por outro lado, a otimização prematura vinda de alguém que não entende o que significa assintótico (a complexidade computacional é uma medida) às vezes é um problema na prática de programação. No entanto, o ponto de saber pelo menos quando a complexidade computacional é importante é por que você precisa ter alguma pista sobre isso, pelo menos no nível de graduação.n2
Eu honestamente ousaria comparar a situação de saber quando aplicar os conceitos de complexidade computacional (e saber quando você pode ignorá-los com segurança) com a prática um pouco comum (fora do mundo Java) de implementar algum código sensível ao desempenho em C e o que não faz sentido coisas em Python etc. (como um aparte, isso foi chamado em uma palestra de Julia como "compromisso padrão" .) Saber quando você não precisa pensar em desempenho economiza tempo de programação, o que também é uma mercadoria bastante valiosa.
E mais um ponto é que conhecer a complexidade computacional não o tornará automaticamente bom em otimizar programas; você precisa entender mais coisas relacionadas à arquitetura, como localidade do cache, [algumas vezes] pipelining e hoje em dia também a programação paralela / multinúcleo; o último também possui sua própria teoria da complexidade e considerações práticas; uma amostra do último de um artigo do SOSP de 2013 "Todo esquema de bloqueio tem seus quinze minutos de fama. Nenhum dos nove esquemas de bloqueio que consideramos supera consistentemente qualquer outro, em todas as arquiteturas ou cargas de trabalho de destino. Estritamente falando, para buscar a otimização, um O algoritmo de bloqueio deve, portanto, ser selecionado com base na plataforma de hardware e na carga de trabalho esperada ".
fonte
Se você não conhece o big-O, deve aprender. Não é difícil e é realmente útil. Comece com a pesquisa e classificação.
Percebo que muitas respostas e comentários recomendam criação de perfil , e quase sempre significam usar uma ferramenta de criação de perfil .
O problema é que as ferramentas de criação de perfil estão espalhadas por todo o mapa em termos de quão eficazes são para encontrar o que você precisa para acelerar. Aqui, listei e expliquei os equívocos dos quais os criadores de perfil sofrem.
O resultado é que os programas, se forem maiores que um exercício acadêmico, podem conter gigantes adormecidos , que nem mesmo o melhor criador de perfil automático pode expor. Esta postagem mostra alguns exemplos de como problemas de desempenho podem ocultar dos criadores de perfil.
Mas eles não podem se esconder dessa técnica.
fonte