Desafio Técnico: Identificar o Segundo Maior Valor em uma Sequência Numérica em Python

Problema

Dada uma lista de elementos, que pode incluir números inteiros, floats e outros tipos de dados, desenvolva uma função para retornar o segundo maior número presente na lista. Trate situações como listas vazias, listas com um único elemento ou contendo itens não numéricos. Inclua testes unitários para validar a solução.

Observações

  • Elimine qualquer elemento que não seja do tipo int ou float antes do processamento.
  • Lide com duplicatas: se o valor máximo ocorrer múltiplas vezes, o segundo maior deve ser o próximo valor distinto inferior ao máximo.
  • Métodos integrados como list.sort(reverse=True) e heapq.nlargest mantêm a contagem de elementos, o que pode incluir duplicatas.

Função de Filtragem de Dados

Criamos uma função para remover elementos inválidos da lista original.


def filtrar_elementos_numericos(entrada):
    """Retorna uma nova lista contendo apenas inteiros ou floats."""
    resultado = []
    for item in entrada:
        if isinstance(item, (int, float)):
            resultado.append(item)
    return resultado

Método 1: Busca Direta

Este método encontra o segundo maior valor sem remover duplicatas previamente.


import sys

def obter_segundo_maior_metodo1(dados):
    lista_filtrada = filtrar_elementos_numericos(dados)
    tamanho = len(lista_filtrada)
    if tamanho == 0:
        print("A lista não contém elementos numéricos.")
        return None
    if tamanho == 1:
        print("Há apenas um número na lista:", lista_filtrada[0])
        return None
    if tamanho > sys.maxsize:
        print("A lista é excessivamente grande.")
        return None
    
    maximo = max(lista_filtrada)
    minimo = min(lista_filtrada)
    if maximo == minimo:
        return None  # Todos os números são iguais
    
    segundo_max = minimo
    for numero in lista_filtrada:
        if numero < maximo and numero > segundo_max:
            segundo_max = numero
    return segundo_max

Testes Unitários

Implementamos uma suíte de testes para validar a função.


import unittest

class TesteObterSegundoMaior(unittest.TestCase):
    
    @classmethod
    def setUpClass(cls):
        print("Iniciando execução dos testes...")
    
    @classmethod
    def tearDownClass(cls):
        print("Testes finalizados.")
    
    def test_lista_vazia(self):
        self.assertIsNone(obter_segundo_maior_metodo1([]))
    
    def test_lista_com_um_elemento(self):
        self.assertIsNone(obter_segundo_maior_metodo1([15]))
    
    def test_apenas_dados_invalidos(self):
        self.assertIsNone(obter_segundo_maior_metodo1([None, "texto", [1, 2]]))
    
    def test_um_numero_apos_filtragem(self):
        self.assertIsNone(obter_segundo_maior_metodo1([None, 7, "abc"]))
    
    def test_maximo_com_duplicatas(self):
        dados = [45, None, 22, "xyz", 10, 8, 50, 5, 45, 6, 50, 12, 30, '40', 50]
        self.assertEqual(obter_segundo_maior_metodo1(dados), 45)

if __name__ == '__main__':
    unittest.main()

Método 2: Eliminação do Máximo

Nesta abordagem, removemos todas as ocorrências do maior elemento e buscamos o novo máximo.


def obter_segundo_maior_metodo2(dados):
    lista_filtrada = filtrar_elementos_numericos(dados)
    if len(lista_filtrada) == 0:
        print("Nenhum número disponível.")
        return None
    if len(lista_filtrada) == 1:
        print("Apenas um número:", lista_filtrada[0])
        return None
    
    valor_maximo = max(lista_filtrada)
    ocorrencias = lista_filtrada.count(valor_maximo)
    while ocorrencias > 0:
        lista_filtrada.remove(valor_maximo)
        ocorrencias -= 1
    
    if not lista_filtrada:
        return None
    return max(lista_filtrada)

Método 3: Ordenação com Valores Únicos

Utilizamos ordenação após remover duplicatas para obter uma lista ordenada de valores distintos.


def obter_segundo_maior_metodo3(dados):
    lista_filtrada = filtrar_elementos_numericos(dados)
    if len(lista_filtrada) == 0:
        print("Lista vazia após filtragem.")
        return None
    if len(lista_filtrada) == 1:
        print("Apenas um número:", lista_filtrada[0])
        return None
    
    lista_sem_duplicatas = list(set(lista_filtrada))
    lista_sem_duplicatas.sort(reverse=True)
    if len(lista_sem_duplicatas) >= 2:
        return lista_sem_duplicatas[1]
    return None

Método 4: Empregando heapq

Arpoveitamos a heapq para extrair os maiores valores de forma eficiente.


import heapq

def obter_segundo_maior_metodo4(dados):
    lista_filtrada = filtrar_elementos_numericos(dados)
    if len(lista_filtrada) == 0:
        print("Sem elementos numéricos.")
        return None
    if len(lista_filtrada) == 1:
        print("Apenas um número:", lista_filtrada[0])
        return None
    
    lista_sem_duplicatas = list(set(lista_filtrada))
    if len(lista_sem_duplicatas) >= 2:
        return heapq.nlargest(2, lista_sem_duplicatas)[1]
    return None

Ao executar os testes, verifique se os caminhos de importação estão configurados corretamente no seu ambiente.

![Estrutura de diretórios recomendada para execução dos testes](https://img-blog.csdnimg.cn/20201217142253605.png?x-oss-process=image/watermark ,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FkUHl0aG9u,size_16,color_FFFFFF,t_70)

Tags: Python listas Algoritmos testes unitários heapq

Publicado em 5-31 19:08 por Thomas