Récemment, j'ai eu une interview, où ils m'ont posé une question de « recherche ».
La question était:
Supposons qu'il existe un tableau d'entiers (positifs), dont chaque élément est l'un
+1
ou l' autre ou-1
comparé à ses éléments adjacents.Exemple:
array = [4,5,6,5,4,3,2,3,4,5,6,7,8];
Recherchez maintenant
7
et restaurez sa position.
J'ai donné cette réponse:
Stockez les valeurs dans un tableau temporaire, triez-les, puis appliquez la recherche binaire.
Si l'élément est trouvé, retournez sa position dans le tableau temporaire.
(Si le nombre se produit deux fois, renvoie sa première occurrence)
Mais, ils ne semblaient pas satisfaits de cette réponse.
Quelle est la bonne réponse?
Réponses:
Vous pouvez faire une recherche linéaire avec des pas qui sont souvent supérieurs à 1. L'observation cruciale est que si par exemple
array[i] == 4
et 7 n'est pas encore apparu, le prochain candidat pour 7 est à l'indexi+3
. Utilisez une boucle while qui va à plusieurs reprises directement au prochain candidat viable.Voici une implémentation, légèrement généralisée. Il trouve la première occurrence de
k
dans le tableau (sous réserve de la restriction + = 1) ou-1
si elle ne se produit pas:production:
la source
O(N)
, mais je ne pense pas qu'il existe un moyen plus rapide de le faire.Votre approche est trop compliquée. Vous n'avez pas besoin d'examiner chaque élément du tableau. La première valeur est
4
, il en7
va de même pour au moins les7-4
éléments, et vous pouvez les ignorer.Sortie du programme:
Edit: amélioré après les commentaires de @Raphael Miedl et @Martin Zabel.
la source
if ((skip = 7 - array[i]) < 1) skip = 1;
semble trop le compliquer et le pessimiser à mon avis. Siarray[i] == 200
vous obtenez-193
et sautez de 1 à chaque fois, même si vous pouvez sauter tous les 193. Pourquoi pas simplementi += abs(7 - array[i])
?skip
la différence absolue entre 7 etarray[i]
.200
, vous l'auriez passé7
.+1
/ les-1
unes des autres. Donc ça pourrait juste êtrearray[0] == 200
et les autres sont pour-1
la plupart .Une variante de la recherche linéaire conventionnelle pourrait être une bonne solution. Prenons un élément disons
array[i] = 2
. Maintenant,array[i + 1]
sera 1 ou 3 (impair),array[i + 2]
sera (entiers positifs uniquement) 2 ou 4 (nombre pair).En continuant ainsi, un modèle est observable -
array[i + 2*n]
contiendra des nombres pairs et ainsi tous ces indices peuvent être ignorés.Aussi, nous pouvons voir que
Ainsi, l'index
i + 5
doit être vérifié ensuite et une boucle while peut être utilisée pour déterminer le prochain index à vérifier, en fonction de la valeur trouvée à l'indexi + 5
.Bien que cela soit complexe
O(n)
(temps linéaire en termes de complexité asymptotique), il vaut mieux qu'une recherche linéaire normale en termes pratiques car tous les indices ne sont pas visités.Évidemment, tout cela sera inversé si
array[i]
(notre point de départ) était étrange.la source
L'approche présentée par John Coleman est ce que l'intervieweur espérait, selon toute probabilité.
Si vous êtes prêt à aller un peu plus compliqué, vous pouvez augmenter la longueur de saut attendue:
Appelez la valeur cible k . Commencez par la valeur du premier élément v à la position p et appelez la différence kv dv avec la valeur absolue av . Pour accélérer les recherches négatives, jetez un œil au dernier élément comme l'autre valeur u à la position o: si dv × du est négatif, k est présent (si une occurrence de k est acceptable, vous pouvez restreindre la plage d'index ici comme le fait la recherche binaire). Si av + au est supérieur à la longueur du tableau, k est absent. (Si dv × du zéro est, v ou u est égal à k.)
Omettre validité d'index: sonde le ( « suivant ») position où la séquence pourrait revenir à v avec k au milieu:
o = p + 2*av
.Si dv × du est négatif, trouver k (récursivement?) De p + av à o-au;
s'il est nul, u vaut k en o.
Si du est égal à dv et que la valeur au milieu n'est pas k, ou au dépasse av,
ou si vous ne trouvez pas k de p + av à o-au,
laissez
p=o; dv=du; av=au;
et continuez à sonder.(Pour un flash-back complet sur les textes des années 60, regardez avec Courier. Ma "1ère 2ème pensée" était d'utiliser
o = p + 2*av - 1
, ce qui exclut du égal à dv .)la source
ÉTAPE 1
Commencez par le premier élément et vérifiez s'il est 7. Disons que
c
c'est l'indice de la position actuelle. Donc, au départ,c = 0
.ÉTAPE 2
Si c'est 7, vous avez trouvé l'index. C'est
c
. Si vous avez atteint la fin du tableau, sortez.ÉTAPE 3
Si ce n'est pas le cas, alors 7 doit être au moins à des
|array[c]-7|
positions éloignées car vous ne pouvez ajouter qu'une unité par index. Par conséquent, ajoutez|array[c]-7|
à votre index actuel, c, et passez à nouveau à l'étape 2 pour vérifier.Dans le pire des cas, lorsqu'il y a des alternances de 1 et -1, la complexité temporelle peut atteindre O (n), mais les cas moyens seraient livrés rapidement.
la source
|c-7|
où cela|array[c]-7|
semble nécessaire.)array[c]-7
peut donc être positif ou négatif. Vous devez en faire la demandeabs()
avant le saut.array[c] - 7
avec l'opérateur de module,|array[c] - 7|
.Ici, je donne l'implémentation en java ...
la source
Voici une solution de style diviser et conquérir. Au détriment de (beaucoup) plus de comptabilité, nous pouvons sauter plus d'éléments; plutôt que de balayer de gauche à droite, testez au milieu et sautez dans les deux sens.
la source
Voulait inclure une solution récursive au problème. Prendre plaisir
la source