Uma resposta objetiva:
Embora minha resposta inicial a essa pergunta tenha sido baseada em minha experiência empírica como estudante de Ciências da Computação e em minha opinião projetada sobre o tipo de pessoas com quem eu queria trabalhar na área de Ciências da Computação. Na verdade, existe uma resposta objetiva (com relação às opiniões subjetivas das sociedades de computação ACM SIGCSE e IEEE). A cada 10 anos, os órgãos da ACM e do IEEE cooperam em uma publicação conjunta que detalha sugestões para o currículo de graduação em ciências da computação com base no conhecimento profissional do estado da indústria da computação. Mais informações podem ser encontradas em cs2013.org . O comitê publica um relatório final listando sua recomendação curricular .
Dito isto, ainda acho que minha lista é muito boa.
Resposta original abaixo.
O que devo saber?
Mínimo
Eu acho que um programador adepto deve ter pelo menos conhecimento de graduação em Ciência da Computação. Certamente, você pode ser eficaz em muitos trabalhos com apenas um pequeno subconjunto de Ciência da Computação, devido à sólida comunidade que o CS assenta e o foco restrito da maioria das posições profissionais. Além disso, muitas pessoas se especializarão após o curso de graduação. No entanto, também não acho que seja uma desculpa para não conhecer o conhecimento básico de CS.
Para responder à pergunta do título, eis o que um estudante de graduação em CS (a base para um programador experiente) deve saber ao se formar:
Estruturas de dados
- Representação de Dados da Máquina
- Uns, complemento de dois e aritmética relacionada
- Palavras, ponteiros, ponto flutuante
- Acesso, deslocamento e manipulação de bits
- Listas Vinculadas
- Tabelas Hash (mapas ou dicionários)
- Matrizes
- Árvores
- Pilhas
- Filas
- Gráficos
- Bases de dados
Algoritmos
- Ordenação:
- Classificação por bolhas (para saber por que é ruim)
- Classificação de inserção
- Mesclar Classificação
- Ordenação rápida
- Classificações de estilo Radix, Classificação de contagem e Classificação de balde
- Heap Sort
- Classificação Bogo e Quantum (=
- Procurando:
- Pesquisa Linear
- Pesquisa binária
- Primeira pesquisa de profundidade
- Primeira Pesquisa de Largura
- Manipulação de String
- Iteração
- Árvore Traversal
- List Traversal
- Funções de hash
- Implementação concreta de uma tabela de hash, árvore, lista, pilha, fila, matriz e conjunto ou coleção
- Algoritmos de agendamento
- Transversal e manipulação do sistema de arquivos (no nível do inode ou equivalente).
Padrões de design
- Modularização
- Fábrica
- Construtor
- Singleton
- Adaptador
- Decorador
- Flyweight
- Observador
- Iterador
- Estado [Máquina]
- Model View Controller
- Padrões de programação de encadeamento e paralelo
Paradigmas
- Imperativo
- Orientado a Objeto
- Funcional
- Declarativo
- Programação estática e dinâmica
- Marcação de dados
Teoria da complexidade
- Espaços de complexidade
- Computabilidade
- Linguagens completas regulares, sem contexto e com máquina universal de Turing
- Expressões regulares
- Contagem e Combinatória Básica
Além
Para entrar no que você está perguntando mais adiante na sua pergunta, se você estiver familiarizado com o exposto acima, poderá identificar facilmente o padrão, o algoritmo e a estrutura de dados apropriados para um determinado cenário. No entanto, você deve reconhecer que geralmente não existe a melhor solução. Às vezes, pode ser necessário escolher o menor dos dois males ou simplesmente escolher entre duas soluções igualmente viáveis. Por isso, você precisa do conhecimento geral para poder defender sua escolha contra seus colegas.
Aqui estão algumas dicas para algoritmos e estruturas de dados:
- A Pesquisa binária pode apenas (e deve) ser usada em dados classificados.
- As classificações de estilo Radix são impressionantes, mas somente quando você tem classes finitas de coisas sendo classificadas.
- As árvores são boas para quase tudo, assim como as Tabelas Hash. A funcionalidade de uma tabela de hash pode ser extrapolada e usada para resolver muitos problemas com o custo de eficiência.
- Matrizes podem ser usadas para fazer backup da maioria das estruturas de dados de nível superior. Às vezes, uma "estrutura de dados" não passa de uma matemática inteligente para acessar locais em uma matriz.
- A escolha do idioma pode ser a diferença entre arrancar os cabelos ou navegar por um problema.
- A tabela ASCII e uma matriz de 128 elementos formam uma tabela de hash implícita (=
- Expressões regulares podem resolver muitos problemas, mas não podem ser usadas para analisar HTML .
- Às vezes, a estrutura de dados é tão importante quanto o algoritmo.
Algumas das opções acima podem parecer sem cérebro, e outras podem parecer vagas. Se você quiser que eu entre em mais detalhes, eu posso. Mas, minha esperança é que, ao encontrar uma pergunta mais concreta, como "Design de uma função que conte o número de ocorrências de cada caractere em uma String", você veja a dica sobre a tabela ASCII e as 128 matrizes de elementos que formam um hash implícito puro tabelas para a resposta.
Com base nessas idéias, proponho uma resposta ao problema do armário descrito em sua pergunta.
Responda ao problema colocado na sua pergunta.
Talvez essa não seja a melhor resposta para sua pergunta, mas acho que é interessante e não exige nada muito complexo. E certamente superará a complexidade de tempo do uso de uma fila ou pilha que requer tempo linear para determinar se um armário está livre ou não.
Você tem 0-999 armários. Agora, como você possui um número fixo de armários, é possível conceber facilmente uma função de hash sem colisões no intervalo de 0 a 999. Essa função é simplesmente h (x) = x mod 1000. Agora, [conceitualmente] construa uma tabela de hash com chaves inteiras e o conteúdo de uma matriz de caracteres de 1000 elementos como seus valores. Se um cliente quiser reservar o armário 78 para uso, basta colocar 78 na função hash (retornar 78) e, em seguida, adicionar esse número ao ponteiro base da matriz - armazenando um valor verdadeiro no local apontado pelo valor de deslocamento . Da mesma forma, se você precisar verificar se 78 está em uso, basta ler o valor armazenado nesse local e verificar se é verdadeiro.
Essa solução opera em tempo constante para pesquisas e armazenamento, em oposição a um armazenamento e pesquisa de tempo de log (n) no caso de uma fila prioritária apoiada por uma árvore binária. A descrição é intencionalmente detalhada, para que você possa ver os conceitos superiores sendo resumidos em um algoritmo eficiente.
Agora, você pode perguntar: e se eu precisar conhecer todos os armários disponíveis, uma fila prioritária não seria melhor? Se houver k cacifos disponíveis na fila de prioridade, a iteração sobre todos eles executará k etapas. Além disso, dependendo da implementação da fila de prioridade, talvez seja necessário reconstruir sua fila de prioridade ao analisar tudo .. o que levaria a etapas k * log (k): (k <1000). Na solução de matriz, você só precisa iterar uma matriz de 1000 elementos e verificar quais estão abertas. Você também pode adicionar uma lista disponível ou usada à implementação para verificar apenas o tempo k.