web-dev-qa-db-fra.com

Comment trouver le seul nombre dans un tableau qui ne se produit pas deux fois

Ce qui suit est tiré d'un entretien d'embauche:

Dans un tableau donné, qui contient des entiers, chaque nombre se répète une fois sauf un, qui ne se répète pas. Ecrivez une fonction qui trouve le nombre qui ne se répète pas.

J'ai pensé à utiliser un HashSet, mais cela pourrait tout compliquer ...

Des idées d'une solution simple?

56
Adam

Vous pouvez définir un "résultat" entier initialisé à 0, puis effectuer certaines opérations au niveau du bit en appliquant une logique XOR) à tous les éléments de votre tableau.

À la fin, "résultat" sera égal au seul élément qui apparaît une seule fois.

result = 0
for i in array:
  result ^= i
return result

http://en.wikipedia.org/wiki/Bitwise_operation#XOR

Par exemple, si votre tableau contient les éléments [3, 4, 5, 3, 4], l’algorithme renverra

3 ^ 4 ^ 5 ^ 3 ^ 4

Mais l'opérateur XOR) est associatif et commutatif, le résultat sera donc égal à:

(3 ^ 3) ^ (4 ^ 4) ^ 5

Puisque i ^ i = 0 pour tout entier i et que i ^ 0 = i, vous avez

(3 ^ 3) ^ (4 ^ 4) ^ 5 = 0 ^ 0 ^ 5 = 5

134
dhokas

J'ai déjà vu cette question. C'est un tour En supposant que tous les nombres répétés apparaissent exactement deux fois, procédez comme suit:

int result = 0;
for (int a : arr)
    result ^= a;
17
Paul Boddington

Encore une autre solution "ordinaire" (en Java):

public static int findSingle(int[] array) {

    Set<Integer> set = new HashSet<Integer>();

    for (int item : array) {
        if (!set.remove(item)) {
            set.add(item);
        }
    }       

    assert set.size() == 1;

    return set.iterator().next();
}

À mon avis, la solution avec XOR est assez belle.

Celui-ci n'est pas aussi rapide que XOR mais l'utilisation de HashSet le rend proche de O (n). Et il est certainement plus lisible.

14
user3078523

La meilleure réponse est déjà donnée (XOR-ing the elements), c’est de fournir une alternative, une manière plus générale.

Si le tableau en entrée devait être trié (nous pouvons le faire), nous pourrions simplement parcourir les éléments par paires (pas à pas de 2) et si les éléments de la "paire" sont différents, nous avons terminé:

public static int findSingle(int[] arr) {
    Arrays.sort(arr);
    for (int i = 0, max = arr.length - 1; i < max; i += 2)
        if (arr[i] != arr[i + 1])
            return arr[i];
    return arr[arr.length - 1]; // Single element is the last
}

Remarque: Cette solution trie le tableau d'entrée. si ceci est indésirable ou non autorisé, il peut être cloné en premier:

arr = arr.clone();

Si le tableau d'entrée est trié, l'appel Arrays.sort(arr) peut être laissé de côté.

Généralisation

L’avantage de cette solution est qu’elle peut être appliquée à tous les types comparables et donc triable (types qui implémentent Comparable ), par exemple String ou Date . La solution XOR est limitée aux nombres.

Voici une version légèrement modifiée qui prend un tableau d'entrée de tout type d'élément comparable:

public static <E extends Comparable<E>> E findSingle(E[] arr) {
    Arrays.sort(arr);
    for (int i = 0, max = arr.length - 1; i < max; i += 2)
        if (arr[i].compareTo(arr[i + 1]) != 0)
            return arr[i];
    return arr[arr.length - 1]; // Single element is the last
}

Remarque: dans la plupart des cas, vous pouvez également utiliser arr[i].equals(arr[i + 1]) pour comparer des éléments au lieu d'utiliser Comparable.compareTo() . Pour plus de détails, lisez le javadoc lié. Citer la partie pertinente:

Il est fortement recommandé, mais pas exigeait strictement que (x.compareTo(y)==0) == (x.equals(y)). De manière générale, toute classe qui implémente l'interface Comparable et qui viole cette condition devrait clairement indiquer ce fait. Le langage recommandé est "Remarque: cette classe a un ordre naturel incompatible avec les égaux."

Maintenant, vous pouvez appeler ceci avec un String[] Par exemple:

System.out.println(findSingle(new String[] { "1", "2", "3", "1", "3" }));

Sortie:

2

Notes finales:

A partir de l'énoncé du problème, il n'est pas vérifié s'il y a plus de 2 occurrences d'éléments, ni si la longueur du tableau est impair. De plus, le deuxième exemple ne vérifie pas les valeurs null, elles doivent être ajoutées si nécessaire.

5
icza

Voici une manière un peu moins obscure de le faire:

List list = Arrays.asList(a);
int result;
for(int i:a)
{
    if(list.indexOf(i)==list.lastIndexOf(i))
    {
        result = i;
        break;
    }
}

result contiendra la valeur non répétée.

2
KSFT