Pular para o conteudo principal

Contém duplicata

Como sair do O(n²) e perceber que o problema só quer saber se você já viu esse valor.

Dado um array de inteiros nums, retorne true se algum valor aparecer pelo menos duas vezes e false se todos os valores forem distintos.

Exemplo:

Input:  nums = [1, 2, 3, 1]
Output: true

O que perceber antes de codar

Erros comuns

Passo 1 — Ler o que realmente esta sendo pedido

Não e um problema de contagem completa.

Não e um problema de achar todas as duplicatas.

O enunciado só quer saber se existe pelo menos uma repetição.

Isso importa porque muda o jeito de pensar:

  • assim que você encontrar uma duplicata, já acabou
  • você não precisa continuar processando o resto

Passo 2 — Escrever a versão mais simples

A primeira solução correta compara cada número com os seguintes:

export function containsDuplicate(nums: number[]): boolean {
  for (let i = 0; i < nums.length; i += 1) {
    for (let j = i + 1; j < nums.length; j += 1) {
      if (nums[i] === nums[j]) {
        return true
      }
    }
  }

  return false
}

Funciona. Mas você repete comparações demais.

Passo 3 — Reformular a pergunta

Em vez de perguntar "com quem este número combina?", aqui a pergunta e mais simples:

o número atual já apareceu antes?

Se você conseguisse responder isso na hora, não precisaria do segundo loop.

Passo 4 — Guardar o que já apareceu

Um conjunto hash resolve exatamente essa parte.

Enquanto percorre o array:

  • se o valor já estiver no conjunto, existe duplicata
  • se não estiver, adicione e continue

O problema inteiro vira uma passada com memória.

O editor interativo precisa de JavaScript. Voce ainda pode ler o desafio e copiar o codigo inicial abaixo.

Codigo inicial

export function containsDuplicate(nums: number[]): boolean {
  // sua solução aqui
  return false
}
solution.ts
Travado? Dicas disponiveis.

Ainda não resolveu?

Ver a solução agora pode reduzir o aprendizado. Vale a pena tentar mais um pouco.

Abrir a solucao de referencia

Sem JavaScript, a solucao de referencia aparece inline em vez de um dialogo.

Solução

Complexidade final

Tempo: O(n)

Espaço: O(n)

Solução 1 — Força bruta O(n²)

Dois loops aninhados. Para cada número, compare com todos os seguintes.

export function containsDuplicate(nums: number[]): boolean {
  for (let i = 0; i < nums.length; i += 1) {
    for (let j = i + 1; j < nums.length; j += 1) {
      if (nums[i] === nums[j]) {
        return true
      }
    }
  }

  return false
}

Funciona. Mas cresce rápido demais porque o array e percorrido várias vezes.

Solução 2 — Conjunto hash em O(n)

Agora a pergunta fica mais alinhada com o problema real:

Eu já vi este valor antes?

Se a resposta puder sair em tempo constante, uma passada basta.

export function containsDuplicate(nums: number[]): boolean {
  const seen = new Set<number>()

  for (const value of nums) {
    if (seen.has(value)) {
      return true
    }

    seen.add(value)
  }

  return false
}

O conjunto hash guarda os valores já vistos. Quando um valor reaparece, você descobre na hora.

O que dizer na entrevista

Uma explicação curta e boa seria:

A versão inicial compara cada número com todos os outros e custa O(n²). Como eu só preciso saber se o valor atual já apareceu, uso um conjunto hash para busca media em O(1) e resolvo em uma passada.

Isso mostra que você:

  • entendeu a versão simples
  • soube explicar por que ela desperdica trabalho
  • escolheu a estrutura de dados certa para a pergunta real

Quando esse padrão aparece de novo

Esse raciocínio volta quando o problema pede:

  • detectar repetição
  • saber se algo já apareceu
  • validar unicidade
  • interromper cedo assim que a condição acontecer

O ponto não e decorar conjunto hash.

O ponto e perceber quando o problema só precisa de memória do que já passou.

Proximo desafio Anagrama válido Desafio anterior Duas somas

Desafios relacionados

Artigos relacionados