Desafio C#

Interseção de conjuntos com Dictionary e HashSet

Enunciado

Dados dois arrays de strings, encontre os elementos comuns a ambos. Use um HashSet<string> para o primeiro array e um Dictionary<string, int> para contar quantas vezes cada elemento aparece no segundo array. Imprima os elementos comuns e suas contagens no segundo array, ordenados alfabeticamente.

Requisitos

  • Usar HashSet<string> para armazenar os elementos do primeiro array.
  • Usar Dictionary<string, int> para contar as ocorrências no segundo array.
  • Imprimir apenas os elementos que estão em ambos, no formato elemento: contagem.
  • Ordenar a saída alfabeticamente pelo elemento.

Código inicial

using System;
using System.Collections.Generic;
using System.Linq;

class Program
{
    static void Main()
    {
        string[] array1 = { "apple", "banana", "orange", "grape" };
        string[] array2 = { "banana", "apple", "apple", "kiwi", "orange", "banana" };
        // Seu código aqui
    }
}

Saída esperada

apple: 2
banana: 2
orange: 1
Ver dica

Primeiro, crie um HashSet<string> com os elementos de array1. Depois, percorra array2 e use TryGetValue para atualizar a contagem no dicionário. Por fim, filtre os elementos que estão no conjunto e ordene.

Mostrar solução
using System;
using System.Collections.Generic;
using System.Linq;

class Program
{
    static void Main()
    {
        string[] array1 = { "apple", "banana", "orange", "grape" };
        string[] array2 = { "banana", "apple", "apple", "kiwi", "orange", "banana" };

        // Conjunto com os elementos do primeiro array
        var conjunto1 = new HashSet<string>(array1);

        // Dicionário para contar ocorrências no segundo array
        var contagens = new Dictionary<string, int>();
        foreach (string item in array2)
        {
            contagens.TryGetValue(item, out int atual);
            contagens[item] = atual + 1;
        }

        // Filtra os elementos que estão no conjunto1 e ordena alfabeticamente
        var comuns = contagens
            .Where(par => conjunto1.Contains(par.Key))
            .OrderBy(par => par.Key);

        foreach (var par in comuns)
        {
            Console.WriteLine($"{par.Key}: {par.Value}");
        }
    }
}

Passo a passo

  1. Criamos um HashSet<string> a partir do array1 para consultas rápidas de pertinência.
  2. Criamos um Dictionary<string, int> para contar quantas vezes cada string aparece no array2.
  3. Iteramos sobre array2; para cada item, usamos TryGetValue para obter a contagem atual (0 se não existir) e atualizamos o dicionário.
  4. Usamos LINQ para filtrar os pares cuja chave está no conjunto1 e ordenamos por chave com OrderBy.
  5. Imprimimos cada par no formato chave: valor.

Por que funciona

O HashSet permite verificar se um elemento está no primeiro array em tempo O(1). O Dictionary acumula as contagens do segundo array também em O(1) por elemento. A combinação das duas estruturas resolve o problema de forma eficiente, sem loops aninhados. A ordenação final garante a saída esperada.

Erros comuns

  • Não usar TryGetValue: tentar acessar contagens[item] diretamente lança exceção se a chave não existir. Use TryGetValue ou GetValueOrDefault.
  • Esquecer de filtrar pelo conjunto: se apenas imprimir todas as contagens, aparecerão elementos que não estão no array1 (ex.: "kiwi").
  • Ordenar antes de filtrar: a ordem não afeta o filtro, mas é mais eficiente filtrar primeiro e ordenar depois.
  • Modificar a coleção durante a iteração: não modifique contagens enquanto itera sobre ela; aqui criamos uma nova sequência com LINQ.

Outra forma de resolver

Poderia usar array1.Intersect(array2) para obter os comuns, mas precisaríamos contar as ocorrências separadamente. A abordagem com HashSet e Dictionary é mais explícita e eficiente para contagens.

Saída esperada

apple: 2
banana: 2
orange: 1