Numeros Maior E Menor
Como encontrar o maior e o menor número em uma lista
Achei que isso fosse simples até tentar processar milhares de valores numéricos de uma vez. Nos primeiros dias aprendendo programação, eu simplesmente ordenava a lista inteira e pegava o primeiro e o último elemento. Funcionava. Até que comecei a notar que isso estava sendo muito lento quando o volume crescia. Basicamente você percorre a sequência uma única vez, mantendo duas variáveis: uma guarda o maior valor encontrado até agora e outra guarda o menor. Não precisa ordenar nada. A ordenação completa custa O(n log n), mas essa abordagem sozinha é O(n), o que significa que para 100 mil números você faz 100 mil comparações em vez de centenas de milhares. No Python, por exemplo, eu usava esse código no início:
menor = lista[0]
maior = lista[0]
para cada numero na lista:
se numero < menor: menor = numero
se numero > maior: maior = numero Simples. Mas aí veio o problema que eu enfrentei na prática. Trabalhando com dados reais de sensores, às vezes a lista vinha vazia ou com apenas um elemento. Quando eu tentava acessar lista[0] num vetor vazio, o programa simplesmente travava. A correção foi adicionar uma verificação inicial bem básica antes de qualquer coisa. Em Java, o tratamento ficou assim:
if (lista.isEmpty()) return null;
List<Integer> numeros = new ArrayList<>(lista);
int menor = numeros.get(0);
int maior = numeros.get(0); Isso evita o erro de indexação fora dos limites. Sem essa proteção, seu sistema pode cair em produção sem aviso.

Por que ordenar não é a melhor opção
Muita gente que está começando pensa: vou usar sort() e pronto. Tá certo, funciona. Mas se sua lista tem 500 mil itens, você está pagando um custo bem alto só para achar dois números. Ordenar rearranja tudo, aloca memória extra, gasta tempo de processador que poderia ser usado em outra coisa. Quando eu medi isso no meu projeto, o ganho era claro. Para uma lista de 10 mil inteiros, a ordenação levava cerca de 3 milissegundos enquanto a passagem única levava menos de 1 milissegundo. A diferença parece pequena, mas em um loop que roda milhares de vezes por segundo, esses milissegundos somam e viram segundos que você não tem. Também tem o caso dos dados com valores nulos ou formatos mistos. Se sua lista vem de uma API externa ou de um arquivo CSV mal formatado, pode ter strings onde deveria ter número. Nesses casos, o método direto já falha na primeira iteração. Eu precisei adicionar um filtro de validação antes do loop principal:
valores_validos = [x para x em lista se isinstance(x, (int, float))] Depois eu aplicava a lógica de maior e menor só nos valores que passaram pela filtragem. Isso resolveu o problema dos dados sujos que apareciam esporadicamente.
Versões para diferentes linguagens
Em JavaScript a abordagem é a mesma. O Math.max e Math.min com spread operator são práticos, mas têm um limite: a lista não pode ser gigante porque o spread passa argumentos como parâmetros de função e existe um teto de quantidade de parâmetros. Para listas grandes em JavaScript, prefira o reduce: const resultado = numeros.reduce((acumulador, atual) => ({
maior: Math.max(acumulador.maior, atual),
menor: Math.min(acumulador.menor, atual)
}), {maior: -Infinity, menor: Infinity});

Em C#, você pode usar LINQ com Min e Max, mas igual ao Python, isso percorre a lista duas vezes. Se quiser eficiência máxima, faça um foreach simples.
Limitações que ninguém conta
Esse método assume que todos os elementos são comparáveis. Se você tiver tipos misturados, como números e strings, a comparação quebra. Também não funciona bem com valores infinitos ou NaN em algumas linguagens, porque NaN não é igual a nada, nem a si mesmo. Num cenário real, eu encontrei células vazias numa planilha que vinham como null e meu loop simplesmente ignorava, mas retornava valores errados porque a variável menor nunca era atualizada corretamente. A solução que eu adotei foi inicializar com o primeiro valor válido encontrado em vez de valores fixos. Assim, mesmo que os primeiros elementos sejam inválidos, o código ainda retorna o certo. Outro ponto importante: em linguagens com tipos fixos como Go ou Rust, se você misturar inteiros com floats, precisa fazer casting antes da comparação. Sem isso, o compilador rejeita. E mesmo com casting, perder precisão pode ocorrer em valores muito grandes.
Se precisar rodar isso em paralelo, divida a lista em partições, encontre o maior e menor de cada parte e depois combine os resultados. O custo adicional da divisão costuma valer a pena quando a lista tem milhões de itens, mas para tamanhos menores o overhead de thread management compensa menos do que o ganho. O essencial é entender que achar numeros maior e menor é trivial na teoria, mas na prática exige atenção aos casos borda: lista vazia, tipos mistos, valores ausentes, infinitos. Tratar esses cenários desde o início evita dores de cabeça depois.

Galeria
-
Atividades sinal de maior e menor | Educlub -
Maior que, Menor que e Igual com o Jacarezinho – Arrisque e Rabisque