J'ai posé cette question sur StackOverflow , mais je pense que c'est un endroit plus approprié.
C'est un problème du cours d' introduction aux algorithmes :
Vous avez un tableau avec entiers positifs (le tableau n'a pas besoin d'être trié ou les éléments sont uniques). Suggérez un algorithme pour trouver la plus grande somme d'éléments divisible par .
Exemple: . La réponse est (avec les éléments 6 , 13 , 4 , 8 , 25 )
Il est relativement facile de trouver dans en utilisant la programmation dynamique et le stockage la plus grande somme avec le reste .
De plus, si nous limitons l'attention à une séquence d'éléments contigus, il est facile de trouver la séquence optimale de ce type en temps , en stockant les sommes partielles modulo : let , pour chaque reste rappelez-vous le plus grand indice tel que , puis pour chaque vous considérez oùest l'indice correspondant à .
Mais existe-t-il une solution en temps pour le cas général? Toute suggestion sera appréciée! Je considère que cela a quelque chose à voir avec l'algèbre linéaire, mais je ne sais pas exactement quoi.
Sinon, cela peut-il être fait en temps ?
la source
Réponses:
Voici quelques idées aléatoires:
L'algorithme de programmation dynamique peut être inversé pour rechercher une plus petite somme au lieu d'une plus grande somme. Vous finissez par chercher une somme congruente au reste de la somme de l'ensemble du tableau, au lieu d'une congruente à zéro. Si nous traitons les éléments dans l'ordre croissant, cela permet parfois à l'algorithme dynamique de se terminer avant de traiter l'ensemble du tableau.
Le coût serait si l'on traitait k éléments. Il n'y a pas de limite inférieure de Ω ( n log n ) sur cet algorithme car nous n'avons pas à trier tous les éléments. Il ne faut que O ( n log k ) pour obtenir les k plus petits éléments.O(nk) k Ω(nlogn) O(nlogk) k
Si nous nous soucions de l'ensemble avec la taille du larget, au lieu de l'ensemble avec la plus grande somme, nous pourrions être en mesure d'utiliser la multiplication polynomiale basée sur la transformée de Fourier rapide pour résoudre le problème dans heure. Similaire à ce qui se fait dans 3SUM lorsque la plage de domaines est limitée. (Remarque: utilisez la quadrature répétée pour faire une recherche binaire, sinon vous obtiendrez O ( n k ( log n ) ( log log n ) ) où kO(n(logn)2(loglogn)) O(nk(logn)(loglogn)) k est le nombre d'éléments omis.)
Lorsque est composite et que presque tous les restes sont un multiple de l'un des n facteurs, un gain de temps significatif peut être gagné en se concentrant sur les restes qui ne sont pas un multiple de ce facteur.n n
Lorsqu'un reste
r
est très fréquent, ou qu'il n'y a que quelques restes présents, garder une trace du `` prochain emplacement ouvert si vous commencez à partir d'ici et continuez à avancerr
'' peut économiser beaucoup de numérisation pour les sauts dans les espaces ouverts temps.Vous pouvez raser un facteur de journalisation en suivant uniquement l'accessibilité et en utilisant des masques de bits (dans l'algorithme dynamique inversé), puis en revenant en arrière une fois que vous atteignez le reste cible.
L'algorithme de programmation dynamique peut très bien être exécuté en parallèle. Avec un processeur pour chaque emplacement de tampon, vous pouvez descendre à . Alternativement, en utilisant la largeur O ( n 2 ) et en divisant et conquérant l'agrégation au lieu de l'agrégation itérative, le coût de la profondeur du circuit peut descendre jusqu'à O ( log 2 n ) .O(n) O(n2) O(log2n)
(Meta) Je soupçonne fortement que le problème qui vous a été posé concerne les sommes contiguës . Si vous vous êtes lié au problème réel, il serait facile de le vérifier. Sinon, je suis très surpris de la difficulté de ce problème, étant donné qu'il a été attribué dans un cours intitulé "Introduction aux algorithmes". Mais peut-être que vous avez couvert un truc en classe qui le rend trivial.
la source
Mon algorithme proposé se présente comme suit:
Une somme est divisible par n si vous ajoutez seulement des sommets qui sont des multiples de n.
Avant de commencer, vous créez une table de hachage avec un int comme clé et une liste d'index comme valeur. Vous créez également une liste de résultats contenant des indices.
Vous bouclez ensuite sur le tableau et ajoutez chaque index dont le mod n est zéro à votre liste de résultats. Pour chaque autre index, vous procédez comme suit:
Vous soustrayez la valeur mod n de cet index de n. Ce résultat est la clé de votre hashmap qui stocke les index des éléments avec la valeur requise. Maintenant, vous ajoutez cet index à la liste dans la table de hachage et continuez.
Après avoir bouclé le tableau, vous calculez la sortie. Pour ce faire, vous triez chaque liste dans la table de hachage en fonction de la valeur vers laquelle l'index pointe. Maintenant, vous considérez chaque paire de la table de hachage résumant à n. Donc, si n = 7, vous recherchez dans la table de hachage pour 3 et 4. Si vous avez une entrée dans les deux, vous prenez les deux plus grandes valeurs, supprimez-les de leurs listes et ajoutez-les à votre liste de résultats.
Dernière recommandation: toujours pas testé l'algorithme, écrivez un testcase contre lui en utilisant un algorithme de force brute.
la source
utilisez cette méthode DP à partir de ( /programming/4487438/maximum-sum-of-non-consecutive-elements?rq=1 ):
Étant donné un tableau A [0..n], soit M (i) la solution optimale en utilisant les éléments d'indices 0..i. Alors M (-1) = 0 (utilisé dans la récurrence), M (0) = A [0], et M (i) = max (M (i - 1), M (i - 2) + A [i ]) pour i = 1, ..., n. M (n) est la solution que nous voulons. C'est O (n) . Vous pouvez utiliser un autre tableau pour stocker le choix effectué pour chaque sous-problème, et ainsi récupérer les éléments réels choisis.
Changez la récursivité en M (i) = max (M (i - 1), M (i - 2) + A [i]) de telle sorte qu'elle ne soit stockée que si elle est divisible par N
la source