Étant donné une matrice NxN avec 0 et 1. Définissez chaque ligne contenant a 0
sur tous les 0
s et définissez toutes les colonnes contenant a 0
sur tous les 0
s.
Par exemple
1 0 1 1 0
0 1 1 1 0
1 1 1 1 1
1 0 1 1 1
1 1 1 1 1
résulte en
0 0 0 0 0
0 0 0 0 0
0 0 1 1 0
0 0 0 0 0
0 0 1 1 0
Un ingénieur Microsoft m'a dit qu'il existe une solution qui n'implique aucune mémoire supplémentaire, juste deux variables booléennes et une passe, donc je cherche cette réponse.
BTW, imaginez que c'est une matrice de bits, donc seuls les 1 et les 0 peuvent être dans la matrice.
algorithm
optimization
puzzle
ancien compte jaircazarin
la source
la source
Réponses:
Ok, donc je suis fatigué car il est 3 heures du matin ici, mais j'ai un premier essai en place avec exactement 2 passes sur chaque nombre de la matrice, donc en O (NxN) et c'est linéaire dans la taille de la matrice.
J'utilise la 1ère colonne et la première ligne comme marqueurs pour savoir où sont les lignes / cols avec seulement 1. Ensuite, il y a 2 variables l et c pour se souvenir si la 1ère ligne / colonne sont toutes des 1 également. Ainsi, la première passe définit les marqueurs et réinitialise le reste à 0.
La deuxième passe définit 1 aux endroits où les lignes et les colonnes sont marquées comme étant 1, et réinitialise la 1ère ligne / colonne en fonction de l et c.
Je doute fortement que je puisse être fait en 1 passage car les carrés au début dépendent des carrés à la fin. Peut-être que mon 2ème passage peut être rendu plus efficace ...
la source
Cela ne peut pas être fait en une seule passe car un seul bit a un effet sur les bits avant et après lui dans n'importe quel ordre. Quel que soit l'ordre dans lequel vous parcourez le tableau, vous pouvez plus tard tomber sur un 0, ce qui signifie que vous devez revenir en arrière et changer un 1 précédent en 0.
Mettre à jour
Les gens semblent penser qu'en limitant N à une valeur fixe (disons 8), vous pouvez résoudre ce problème en une seule passe. Eh bien, c'est a) manquer le point et b) pas la question d'origine. Je ne publierais pas de question sur le tri et j'attendrais une réponse commençant "en supposant que vous ne vouliez trier que 8 choses ...".
Cela dit, c'est une approche raisonnable si vous savez que N est en fait limité à 8. Ma réponse ci-dessus répond à la question initiale qui n'a pas une telle restriction.
la source
Mon idée est donc d'utiliser les valeurs de la dernière ligne / colonne comme indicateur pour indiquer si toutes les valeurs de la colonne / ligne correspondante sont des 1.
En utilisant un balayage Zig Zag sur toute la matrice SAUF la dernière ligne / colonne. À chaque élément, vous définissez la valeur dans la dernière ligne / colonne comme le ET logique de lui-même avec la valeur de l'élément actuel. En d'autres termes, si vous atteignez un 0, la dernière ligne / colonne sera définie sur 0. Si vous avez un 1, la valeur de la dernière ligne / colonne sera 1 seulement si elle était déjà 1. Dans tous les cas, définissez l'élément actuel sur 0.
Lorsque vous avez terminé, votre dernière ligne / colonne doit avoir des 1 si la colonne / ligne correspondante est remplie de 1.
Effectuez un balayage linéaire de la dernière ligne et de la dernière colonne et recherchez les 1. Définissez des 1 dans les éléments correspondants dans le corps de la matrice où la dernière ligne et la dernière colonne sont toutes deux des 1.
Le codage sera difficile pour éviter les erreurs ponctuelles, etc., mais cela devrait fonctionner en un seul passage.
la source
J'ai une solution ici, elle s'exécute en un seul passage, et fait tout le traitement "en place" sans mémoire supplémentaire (sauf pour agrandir la pile).
Il utilise la récursivité pour retarder l'écriture des zéros, ce qui détruirait bien sûr la matrice pour les autres lignes et cols:
la source
Je ne pense pas que ce soit faisable. Lorsque vous êtes sur le premier carré et que sa valeur est 1, vous n'avez aucun moyen de savoir quelles sont les valeurs des autres carrés de la même ligne et colonne. Vous devez donc les vérifier et s'il y a un zéro, revenez au premier carré et changez sa valeur en zéro. Je recommande de le faire en deux passes - la première passe rassemble des informations sur les lignes et les colonnes qui doivent être mises à zéro (les informations sont stockées dans un tableau, nous utilisons donc de la mémoire supplémentaire). La deuxième passe modifie les valeurs. Je sais que ce n'est pas la solution que vous recherchez, mais je pense que c'est une solution pratique. Les contraintes que vous donnez rendent le problème insoluble.
la source
Je peux le faire avec deux variables entières et deux passes (jusqu'à 32 lignes et colonnes ...)
la source
~
inverse tous les bits d'une variable. 0x00000000 devient 0x00000000. Je commence essentiellement par tous les uns, et efface le bit pour une ligne / colonne lorsque je trouve un 0. CompleteCols a les bits 2 et 3 définis, et CompleteRows a les bits 2 et 4 définis (basés sur 0).le problème peut être résolu en un seul passage
sauvegarde de la matrice dans un tableau i X j.
maintenant imprimer toutes les valeurs comme 0 pour les valeurs de i et j enregistrées dans a et b le reste des valeurs est 1 c'est-à-dire (3,3) (3,4) (5,3) et (5,4)
la source
Une autre solution qui prend deux passes, consiste à accumuler les ET horizontalement et verticalement:
Je pensais pouvoir concevoir un tel algorithme en utilisant des bits de parité , des codes de Hamming ou une programmation dynamique , en utilisant éventuellement ces deux booléens comme nombre à 2 bits, mais je n'ai pas encore réussi.
Pouvez-vous s'il vous plaît revérifier l'énoncé du problème avec votre ingénieur et nous le faire savoir? S'il est en effet une solution, je veux garder grignote le problème.
la source
Gardez une seule variable pour garder une trace de ce que sont toutes les lignes ET ensemble.
Si une ligne vaut -1 (tous les 1), alors faites de la ligne suivante une référence à cette variable
Si une ligne est autre chose, c'est un 0. Vous pouvez tout faire en un seul passage. Code pseudo:
Cela devrait le faire, en une seule passe - mais il y a une hypothèse ici que N est suffisamment petit pour que le processeur fasse de l'arithmétique sur une seule ligne, sinon vous devrez boucler sur chaque ligne pour déterminer si tout est 1s ou pas, je crois. Mais étant donné que vous posez des questions sur les algos et que vous ne contraignez pas mon matériel, je commencerais simplement ma réponse par "Construisez un processeur prenant en charge l'arithmétique N-bit ..."
Voici un exemple de la façon dont cela peut être fait en C. Remarque Je soutiens que les valeurs et arr pris ensemble représentent le tableau, et p et numproduct sont mon itérateur et les variables de produit AND utilisent pour implémenter le problème. (J'aurais pu faire une boucle sur arr avec l'arithmétique du pointeur pour valider mon travail, mais une fois c'était suffisant!)
Cela produit 0, 0, 6, 0, 6, qui est le résultat pour les entrées données.
Ou en PHP, si les gens pensent que mes jeux de pile en C trichent (je vous suggère que ce n'est pas le cas, car je devrais pouvoir stocker la matrice comme je veux):
Est-ce que je manque quelque chose?
la source
Beau défi. Cette solution utilise en quelque sorte seulement deux booléens créés sur la pile, mais les booléens sont créés plusieurs fois sur la pile car la fonction est récursive.
Cela scanne dans un modèle comme:
etc
Et puis changer les valeurs de ce modèle au retour sur chacune des fonctions de scan. (De bas en haut):
etc
la source
Ok, c'est une solution qui
la source
Réellement. Si vous voulez simplement exécuter l'algorithme et imprimer les résultats (c'est-à-dire ne pas les restaurer, alors cela peut facilement être fait en un seul passage. Le problème survient lorsque vous essayez de modifier le tableau pendant que vous exécutez l'algorithme.
Voici ma solution. Il s'agit simplement de mettre en ET les valeurs de lignes / colonnes pour un élément de givein (i, j) et de l'imprimer.
la source
J'ai essayé de résoudre ce problème en C #.
J'ai utilisé deux variables de boucle (i et j) en dehors de la matrice réelle et n représentant sa dimension
La logique que j'ai essayée est de:
Code:
la source
One Pass - J'ai parcouru l'entrée une seule fois, mais j'ai utilisé un nouveau tableau et seulement deux variables booléennes supplémentaires.
la source
Bien que cela soit impossible compte tenu des contraintes, le moyen le plus efficace de le faire en termes d'espace consiste à traverser la matrice de manière chevauchante et alternée de lignes / colonnes, ce qui donnerait un motif similaire à la pose de briques en zig-zag:
En utilisant cela, vous iriez dans chaque ligne / colonne, comme indiqué, et si vous rencontrez un 0 à tout moment, définissez une variable booléenne et parcourez à nouveau cette ligne / colonne, en définissant les entrées sur 0 au fur et à mesure.
Cela ne nécessitera aucune mémoire supplémentaire et n'utilisera qu'une seule variable booléenne. Malheureusement, si le bord "lointain" est défini sur 0, c'est le pire des cas et vous parcourez l'ensemble du tableau deux fois.
la source
créer une matrice de résultats et définir toutes les valeurs sur 1. parcourir la matrice de données dès qu'un 0 est rencontré, définir la colonne de ligne de matrice de résultats sur 0
À la fin du premier passage, la matrice de résultats aura la bonne réponse.
Ça a l'air assez simple. Y a-t-il un truc qui me manque? N'êtes-vous pas autorisé à utiliser un jeu de résultats?
ÉDITER:
Cela ressemble à une fonction F #, mais c'est un peu triche car même si vous faites une seule passe, la fonction peut être récursive.
Il semble que l'intervieweur essaie de déterminer si vous connaissez la programmation fonctionnelle.
la source
Eh bien, j'ai proposé une solution en place (non récursive) en un seul passage utilisant 4 booléens et 2 compteurs de boucle. Je n'ai pas réussi à le réduire à 2 bools et 2 ints, mais je ne serais pas surpris si c'était possible. Il fait environ 3 lectures et 3 écritures de chaque cellule, et il devrait être O (N ^ 2) ie. linéaire dans la taille du tableau.
Il m'a fallu quelques heures pour résoudre celui-ci - je ne voudrais pas avoir à le trouver sous la pression d'une interview! Si j'ai fait un booboo, je suis trop fatigué pour le repérer ...
Euh ... Je choisis de définir "single-pass" comme faisant un balayage à travers la matrice, plutôt que de toucher chaque valeur une fois! :-)
la source
j'espère que vous apprécierez ma solution c # en 1 passage
vous pouvez récupérer un élément avec O (1) et n'avez besoin que de l'espace d'une ligne et d'une colonne de la matrice
la source
1 passage, 2 booléens. Je dois juste supposer que les index entiers dans les itérations ne comptent pas.
Ce n'est pas une solution complète mais je ne peux pas passer ce point.
Si je pouvais seulement déterminer si un 0 est un 0 original ou un 1 qui a été converti en 0, je n'aurais pas à utiliser des -1 et cela fonctionnerait.
Ma sortie est comme ceci:
L'originalité de mon approche consiste à utiliser la première moitié de l'examen d'une ligne ou d'une colonne pour déterminer si elle contient un 0 et la dernière moitié pour définir les valeurs - cela se fait en regardant x et width-x puis y et height -y à chaque itération. Sur la base des résultats de la première moitié de l'itération, si un 0 dans la ligne ou la colonne a été trouvé, j'utilise la dernière moitié de l'itération pour changer les 1 en -1.
Je viens de réaliser que cela pouvait être fait avec seulement 1 booléen laissant 1 à ...?
Je publie ceci en espérant que quelqu'un dira: "Ah, fais juste ça ..." (Et j'ai passé beaucoup trop de temps dessus pour ne pas poster.)
Voici le code en VB:
la source
Personne n'utilise des formes binaires? puisque ce n'est que 1 et 0. Nous pouvons utiliser des vecteurs binaires.
Voici le test:
Et la sortie:
la source
Vous pouvez faire quelque chose comme ceci pour utiliser une passe mais une matrice d'entrée et de sortie:
où
col(xy)
sont les bits dans la colonne contenant le pointxy
;row(xy)
correspond aux bits de la ligne contenant le pointxy
.n
est la taille de la matrice.Ensuite, faites une boucle sur l'entrée. Peut-être extensible pour être plus efficace en termes d'espace?
la source
Un scan matriciel, deux booléens, pas de récursivité.
Comment éviter le deuxième passage? La deuxième passe est nécessaire pour effacer les lignes ou les colonnes lorsque le zéro apparaît à leur fin.
Cependant, ce problème peut être résolu, car lorsque nous analysons la ligne #i, nous connaissons déjà l'état de la ligne # i-1. Ainsi, pendant que nous analysons la ligne #i, nous pouvons simultanément effacer la ligne # i-1 si nécessaire.
La même solution fonctionne pour les colonnes, mais nous devons analyser les lignes et les colonnes simultanément pendant que les données ne sont pas modifiées par l'itération suivante.
Deux booléens sont nécessaires pour stocker l'état de la première ligne et de la première colonne, car leurs valeurs seront modifiées lors de l'exécution de la partie principale de l'algorithme.
Pour éviter d'ajouter plus de booléens, nous stockons l'indicateur "clear" pour les lignes et colonnes de la première ligne et colonne de la matrice.
la source
semble que ce qui suit fonctionne sans aucune exigence d'espace supplémentaire:
notez d'abord que multiplier les éléments de la ligne par les éléments de la ligne dans laquelle se trouve un élément, donne la valeur souhaitée.
Afin de ne pas utiliser d'espace supplémentaire (ne pas créer une nouvelle matrice et la remplir, mais appliquer les modifications directement à la matrice), commencez en haut à gauche de la matrice et faites le calcul pour toute matrice ixi (qui "commence" à (0 , 0)) avant de considérer tout élément avec un indice> i.
j'espère que cela fonctionne (havent testet)
la source
Ceci est TESTÉ pour différents N en C ++, et est:
UN PASS , DEUX BOOLS , PAS DE RÉCURSION , PAS DE MÉMOIRE SUPPLÉMENTAIRE , TENUE POUR ARBITRARLY LARGE N
(Jusqu'à présent, aucune des solutions ici ne fait TOUTES celles-ci.)
Plus précisément, je suis amusant que les compteurs de deux boucles fonctionnent. J'ai deux const unsigneds, qui n'existent que plutôt que d'être calculés à chaque fois pour la lisibilité. L'intervalle de la boucle externe est [0, N] et l'intervalle de la boucle interne est [1, n - 1]. L'instruction switch est dans la boucle existe principalement pour montrer très clairement qu'il ne s'agit en réalité que d'un seul passage.
Stratégie d'algorithme:
La première astuce est pour nous une ligne et une colonne de la matrice elle-même pour accumuler le contenu de la matrice, cette mémoire devient disponible en déchargeant tout ce que nous avons vraiment besoin de savoir de la première ligne et colonne dans deux booléens. La deuxième astuce consiste à obtenir deux passes sur une, en utilisant la symétrie de la sous-matrice et ses indices.
Synopsis de l'algorithme:
Implémentation en modèle C ++:
la source
Ok, je me rends compte que ce n'est pas tout à fait une correspondance, mais je l'ai obtenu en un seul passage en utilisant un booléen et un octet au lieu de deux booléens ... fermer. Je ne garantirais pas non plus son efficacité, mais ces types de questions nécessitent souvent des solutions moins qu'optimales.
la source
Vous pouvez le faire en un seul passage - si vous ne comptez pas accéder à la matrice dans un ordre d'accès aléatoire, ce qui élimine les avantages de le faire en un seul passage en premier lieu (cohérence du cache / bande passante mémoire).
[modifier: solution simple, mais incorrecte supprimée]
Vous devriez obtenir de meilleures performances que n'importe quelle méthode en un seul passage en le faisant en deux passes: une pour accumuler les informations de ligne / colonne et une pour l'appliquer. Le tableau (dans l'ordre des lignes principales) est accessible de manière cohérente; pour les tableaux dépassant la taille du cache (mais dont les lignes peuvent tenir dans le cache), les données doivent être lues à partir de la mémoire deux fois et stockées une fois:
la source
La solution la plus simple à laquelle je puisse penser est collée ci-dessous. La logique consiste à enregistrer la ligne et la colonne à mettre à zéro lors de l'itération.
la source
Voici mon implémentation Ruby avec le test inclus, cela prendrait de l'espace O (MN). Si nous voulons une mise à jour en temps réel (comme pour afficher les résultats lorsque nous trouvons des zéros plutôt que d'attendre la première boucle de recherche de zéros), nous pouvons simplement créer une autre variable de classe comme
@output
et chaque fois que nous trouvons un zéro, nous mettons à jour@output
et non@input
.la source
Le code ci-dessous crée une matrice de taille m, n. Décidez d'abord des dimensions de la matrice. Je voulais remplir la matrice [m] [n] de façon aléatoire avec des nombres entre 0..10. Créez ensuite une autre matrice de mêmes dimensions et remplissez-la de -1s (matrice finale). Ensuite, parcourez la matrice initiale pour voir si vous atteindrez 0. Lorsque vous frappez sur l'emplacement (x, y), allez à la matrice finale et remplissez la ligne x avec des 0 et la colonne y avec des 0. À la fin, lisez la matrice finale, si la valeur est -1 (valeur d'origine), copiez la valeur au même emplacement de la matrice initiale vers final.
la source
voici ma solution. Comme vous pouvez le voir dans le code, étant donné une matrice M * N, il met la ligne entière à zéro une fois qu'il inspecte un zéro dans cette ligne.la complexité temporelle de ma solution est O (M * N). Je partage toute la classe qui a un tableau rempli statique pour les tests et une méthode de tableau d'affichage pour voir le résultat dans la console.
}
la source