Recentemente colocámos neste blog um post com um dos problemas que usamos em muitas das entrevistas de 2009 no SAPO.
O problema consistia em desenhar (escrever) um algoritmo para resolver o seguinte problema, em pseudo-código:
"Vais receber uma lista de números. Encontra a maior diferença entre quaisquer dois números nessa lista."
Hoje vamos analisar algumas das soluções com que nos deparámos nas entrevistas.
Estranhamente, uma solução que é apresentada com frequência é a seguinte:
maior_diferenca = 0;
for ( i = 1 ; i < length lista ; i++ ) {
if ( lista[i] - lista[i-1] > maior_diferenca ) {
maior_diferenca = lista[i] - lista[i-1];
}
}
return maior_diferenca;
Esta é uma solução que não apresenta o resultado correcto e que demonstra uma série de problemas no raciocínio do candidato (problemas esses que não iremos abordar aqui, mas é de facto uma situação comum).
Eis a solução mais básica que poderia ser apresentada (seguindo-se a lista de problemas que a mesma apresenta):
maior_diferenca = 0;
for ( i = 0 ; i < length lista ; i++ ) {
for ( j = 0 ; j < length lista ; j++ ) {
if ( abs( lista[i] - lista[j] > maior_diferenca ) ) {
maior_diferenca = abs( lista[i] - lista[j] );
}
}
}
return maior_diferenca;
Problemas de eficiência:
Erros e corner-cases:
Vejamos agora a mesma solução já com alguns destes problemas resolvidos:
maior_diferenca = 0;
tamanho = length lista;
for ( i = 0 ; i < tamanho ; i++ ) {
for ( j = i+1 ; j < tamanho ; j++ ) {
diferenca = abs( lista[i] - lista[j] );
if ( diferenca_actual > maior_diferenca ) ) {
maior_diferenca = diferenca_actual;
}
}
}
return maior_diferenca;
Apesar de esta solução ainda não estar a prever os casos da lista vazia ou da lista com um único elemento, esta já é uma solução mais eficiente que a anterior.
Ainda assim, um bom candidato consegue, desde o início, compreender que não necessita realizar tantas operações, já que lhe basta encontrar o maior e o menor elemento da lista e calcular a diferença entre dois.
Infelizmente, isto faz com que alguns candidatos apresentem uma solução semelhante à seguinte:
lista = sort lista;
max = last lista;
min = first lista;
return max - min;
Apesar da solução estar correcta, não é de todo eficaz, dada a complexidade de um sort numa lista com, por exemplo, 20,000 valores.
Eis uma outra solução seguindo esta ideia, ainda com alguns problemas:
min = 0;
max = 0;
for ( i = 0; i < tamanho; i++ ) {
if ( lista[i] < min ) {
min = lista[i];
}
if ( lista[i] > max ) {
max = lista[i];
}
}
return max - min;
Esta é uma solução que não funciona, uma vez que basta que todos os números sejam positivos ou negativos para retornar o valor errado.
Uma melhor solução seria algo no seguinte sentido:
min = null;
max = null;
for ( i = 0; i < tamanho; i++ ) {
if ( min == null or lista[i] < min ) {
min = lista[i];
}
if ( max == null or lista[i] > max ) {
max = lista[i];
}
}
if ( min != null and max != null ) {
return max - min;
}
else {
# ...
}
Entre todas estas versões, há ainda mais uma série de variantes que outros candidatos apresentam.
Há também questões específicas de cada linguagem que podem fazer com que pequenas partes devam ser alteradas por uma questão de eficiência.
Ao ser confrontado com este problema, o candidato ideal:
Convém ainda deixar claro que este é apenas um problema que fez parte de um grande conjunto de desafios colocados aos candidatos e que não é apenas a resolução de um simples problema que dita o recrutamento ou não da pessoa.