On m'a donné le problème suivant dans une interview (que j'ai déjà échoué à résoudre, n'essayant pas de me tromper): Le jeu commence avec un nombre entier positif . (Par exemple ) Ce nombre est converti en représentation binaire, et est le nombre de bits mis à . (Par exemple , )
Le joueur 1 choisit un nombre inférieur à . doit avoir qu'un seul bit mis à 1. (Par exemple ) Soit . (Par exemple ). Un mouvement est valide si satisfait les contraintes précédentes, et si le nombre de bits mis en est toujours égal à n .A 0 B 0 B 0 = b 10 0000 0000 = 512 A 1 = A 0 - B 0 A 1 = 1234 - 512 = 722 = b 10 1101 0010 B 0 A 1
Le joueur 2 continue depuis en choisissant un valide , puis le joueur 1 continue depuis , et ainsi de suite. Un joueur perd s'il n'a plus de coups valides.B 1 A 2
En supposant que les deux joueurs jouent de manière optimale, déterminez le joueur gagnant en utilisant une méthode raisonnablement efficace. (Dans ma définition de problème, les contraintes à cela étaient que le programme devait être en mesure de fournir une solution pour quelques millions de nombres d'entrée qui correspondent à un entier signé de 32 bits.) Autrement dit, la solution n'a pas besoin d'être entièrement analytique.
Mon intérêt personnel ici est de déterminer si l'attente de moi d'avoir trouvé et mis en œuvre la bonne solution sans aucun retour sur l'exactitude dans les 120 minutes qui m'ont été donnée était raisonnable; ou si c'était l'une de ces questions "voyons s'ils ont déjà vu ce puzzle".
J'avais échoué parce que j'avais choisi de mettre en œuvre ce qui semblait être une stratégie raisonnable, ce qui m'a donné des résultats corrects pour les quelques cas de test qui m'avaient été donnés à l'avance, j'ai perdu trop de temps à accélérer cette course et j'ai fini par remettre des données incorrectes. pleine sortie que mon temps est écoulé.
Rétrospectivement, j'aurais dû implémenter une recherche par force brute et mémoriser des solutions partielles pour les petits nombres de départ, mais le recul est toujours de 20/20. Je suis curieux cependant s'il y a une approche commune différente qui m'a échappé en tant que flunkee.
la source
Réponses:
Prenez un moment pour vous rendre compte que si nous ne pouvons soustraire qu'un pouvoir de deux, et que le nombre ne peut pas changer, nous devons soustraire dans une position où l'autre nombre est . Le résultat est toujours dans cette position, et le nombre ne change nulle part ailleurs.10 0101 10 01
En d'autres termes, le jeu est une série de swaps de , et le jeu se termine si tous sont du côté droit. Notez qu'il est impossible que ce jeu se termine tôt - vous ne pouvez pas rester bloqué. Vous vous retrouverez toujours à une position où tous les zéros sont à gauche et tous ceux à droite.10→01
Donc, le seul facteur déterminant dans un jeu est le nombre de swaps nécessaires pour arriver à l'état où tous sont à droite, et il n'y a pas de stratégie gagnante ou perdante. La parité du nombre de swaps qu'il faut est le seul facteur déterminant.
Alors, combien de swaps faut-il? Notez que les ne peuvent pas se croiser, donc si nous les numérotions et les suivions via des swaps, ils resteraient dans le même ordre dans l'état final. Chaque échange les rapproche de leur position finale.1
Donc, si le th (en comptant à partir de la droite, le le plus à droite est le th ) est en position partir de la droite, il a besoin de swaps pour arriver à sa position correcte. Cela nous donne un algorithme pour compter le nombre de swaps requis:1 1 0 1 k k - ii 1 1 0 1 k k−i
Nous pouvons maintenant regarder la parité deO(logn)
total
pour voir qui gagne. La complexité temporelle est .la source
Une façon de résoudre un tel problème est la suivante:
Trouvez la solution pour quelques valeurs simples en utilisant l'approche de "force brute mémorisée" que vous proposez.
Devinez la réponse (quelles positions gagnent et lesquelles perdent).
Essayez de prouver votre réponse. Si vous réussissez, tant mieux. Sinon, essayez de trouver un contre-exemple et utilisez-le pour deviner une autre réponse. Ici, il pourrait être utile de résoudre quelques cas supplémentaires.
Il est vraiment difficile de dire combien de temps cela prend. Cependant, lors des entretiens, vous ne devez pas nécessairement trouver la solution. Les enquêteurs veulent plutôt savoir comment vous avez abordé la résolution du problème et quels progrès vous avez réussi à réaliser.
la source
Notez de la réponse de @ orlp que nous voulons la parité de la somme des déplacements de la position de départ à la position de fin. Annotons ceci:
Nous voulons donc
La première partie est juste la parité du nombre de bits dans les positions impaires. Vous pouvez masquer cela en prenant le nombre entier non signé maximum, en divisant par 0b11 et en niant.
La deuxième partie est la parité de la moitié du nombre de bits
x
.bitcount
peut soit utiliser l'popcnt
instruction matérielle , soit être implémentée manuellement en utilisant uniquement le dernier ou l'avant-dernier bit, avec des réductions rapides comme celle-ci .la source