0
votes

Problème Trouver des numéros en double dans la matrice, ma technique est-elle mauvaise?

J'ai utilisé un haschmap pour stocker les occurrences de chaque élément, puis itéré sur la carte de hachage pour obtenir un élément dupliqué, mais quelque chose ne se sent pas juste à propos de cette solution.

Déclaration de problème dans FIRECODE.IO: p>

Écrire une méthode en double pour trouver les éléments répétés ou en double dans un tableau. Cette méthode doit renvoyer une liste d'entiers répétés dans une chaîne avec les éléments triés par ordre croissant (comme illustré ci-dessous). P>

duplicate ({1,3,4,2,1}) code> -> "[1]" code> p> p>

duplicate ({1,3,4,2,1,2,4}) code> -> "[1, 2, 4]" code> p >

Remarque: Vous pouvez utiliser la méthode Tostring () pour renvoyer la représentation standard de la chaîne de la plupart des structures de données et des tableaux.sort () pour trier votre résultat. * P> BlockQuote>

Voici mon code: P>

 public String duplicate(int[] numbers) {
      HashMap < Integer, Integer > hs = new HashMap < Integer, Integer > ();
      for (int i = 0; i < numbers.length; i++) {
           if (hs.get(numbers[i]) == null) {
                hs.put(numbers[i], 1);
           } else hs.put(numbers[i], (Integer) hs.get(numbers[i]) + 1);
      }

      int size = 0;
      for (int i: hs.keySet()) {
           if (hs.get(i) > 1) {
                size++;
           }
      }
      int j = 0;
      int[] a = new int[size];
      for (int i: hs.keySet()) {
           if (hs.get(i) > 1) {
                a[j++] = i;
           }
      }

      Arrays.sort(a);
      return Arrays.toString(a);
 }


5 commentaires

Est-il vraiment nécessaire de dupliquer le texte?


Qu'est-ce que vous n'aimez pas exactement ce que vous n'aimez pas?


"Quelque chose ne se sent pas bien" est un peu vague comme une description problématique. Non liée: prenez l'habitude de toujours être cohérente sur l'utilisation des accolades pour si-ele blocs


Je pense que cette question est dans le mauvais débordement. Il conviendrait mieux pour codereview.stackexchange.com


Stackoverflow.com/a/31341963/1121249


4 Réponses :


0
votes

Vous n'avez pas besoin d'une autre boucle pour obtenir la valeur de la taille code>.

remplacer p> xxx pré>

avec p>

HashMap < Integer, Integer > hs = new HashMap < Integer, Integer > ();
int size=0;
for (int i = 0; i < numbers.length; i++) {
   if (hs.get(numbers[i]) == null) {
        hs.put(numbers[i], 1);
   } else {
        hs.put(numbers[i], (Integer) hs.get(numbers[i]) + 1);
        size++;
   }
}


0 commentaires

1
votes

Étant donné que vous n'avez pas à dire combien de fois un élément est dupliqué, vous n'avez besoin que d'un définir code> pour mémoriser quels éléments sont uniques et qui non. Si vous connaissez les valeurs d'élément (par exemple, les nombres entre 1 et 10), vous pouvez simplifier davantage définir code> sur booléen [] code> ou un vecteur bit:

int[] numbers = {1, 3, 4, 2, 2, 1, 2, 4, 4};
Set<Integer> unique = new HashSet<>();
Set<Integer> duplicates = new HashSet<>();
for (int n : numbers) {
    if (!unique.add(n)) {
        duplicates.add(n);
    }
}
List<Integer> result = new ArrayList<>(duplicates);
result.sort(Integer::compareTo);
System.out.println(result); // [1, 2, 4]


3 commentaires

On dirait très la réponse à la réponse que j'ai presque donné, jusqu'à ce que je me rendais compte que vous puissiez utiliser arbreset <> pour la valeur de la valeur et ignorez la phase de tri complète.


Arbreset échangerait un coût d'insertion pour le tri du tri Liste à la fin. Il n'y a pas une chose comme un déjeuner gratuit.


Vrai, mais il réduit la charge cognitive d'essayer de comprendre la méthode. Il supprime également la nécessité de copier des valeurs hors du duplicate dans la liste (code>. La surcharge du maintien d'un arbre pourrait s'éteindre le coût de l'exécution, mais ce n'est pas le cas. FWIW, vous pouvez utiliser collections.sort (résultat) pour éviter le entier :: comparèteto .



0
votes

Si vous utilisez Java 8 ou au-delà, vous pouvez essayer:

public String duplicate(int[] numbers) {
    Map<Integer, Integer> hs = new HashMap<>();
    for ( int i : numbers ) {
        hs.merge( i, 1, Integer::sum);
    }
    return '[' + 
             hs.entrySet()
               .stream()
               .filter( e -> e.getValue() > 1 )
               .map(Entry::getKey)
               .sorted()
               .map(i -> i.toString())
               .collect(Collectors.joining(", ")) +
           ']';
}


1 commentaires

trop streamy peut-être



2
votes

Voici la façon dont je le ferais: (Commentaires à des fins éducatives ne les aurait probablement pas dans le code de production.)

public String duplicate(int[] numbers) {

  // holds the items we've encountered more than once.
  // TreeSet<> keeps things in sorted order for us.
  final SortedSet<Integer> duplicates = new TreeSet<>();

  // keeps track of items we've encountered.
  final Set<Integer> encountered = new HashSet<>(); 

  // iterate over every number
  for (final int number : numbers) {
    // Add the item to encountered. Set.add() will return true if 
    // the element is new to the set.
    if (!encountered.add(number)) {
       // Since the element wasn't new, ensure this item exists in the duplicates collection.
       duplicates.add(number);
    }
  }

  return duplicates.toString();
}


3 commentaires

J'utiliserais triés duplicates = nouveau arbreset <> () pour signifier pourquoi nous avons arbreset .


J'ai pensé à ça @karoldowbecki, mais j'ai décidé que, étant donné que nous n'avions pas besoin des méthodes dans Saitedset , il n'était pas nécessaire. À cette fin, j'aurais pu les faire tous Collection , je suppose. haussement d'épaules sa subjective.


@Karoldowbecki, j'ai décidé d'aller avec votre suggestion et j'ai édité ma réponse.