Comment trouver le nombre de valeurs dans une plage donnée divisible par une valeur donnée?
J'ai trois nombres x, y , z.
Pour une gamme entre les nombres x et y.
Comment puis-je trouver le nombre total dont % avec z est 0 c'est à dire combien de nombres entre x et y sont divisible par z ?
- Si c'est un devoirs, peut-être le bon vieux ennuyeux et lent "essayez de chacun et compter" on va le faire.
- non, pas des devoirs à faire.... j'en ai besoin pour certains d'optimisation.
- Si ce n'est pas des devoirs à faire, retirez le C et le C++ tags, ajouter un algorithme tag et peut-être faire un peu de réflexion (astuce: trouver le premier un en O(1), trouver le dernier en O(1), de trouver le nombre de tous les autres en O(1))
|x - y| / z
=|10 - 2| / 3
ou|100 - 10| / 5
ou ...?- ça va pas le faire. Il y a trois nombres pairs dans
[1..5]
, mais seulement deux dans[2..6]
- +1 parce que je veux Hobbs solution examines et outscore la mienne si elle est correcte 😉 et parce que cette question est assez générale pour mériter une solution optimale
Vous devez vous connecter pour publier un commentaire.
Il peut être fait en O(1): trouver la première, trouver le dernier, de trouver le nombre de tous les autres.
Je suis en supposant que la plage est inclusive. Si vos gammes sont exclusifs, d'ajuster les limites par un:
trouver la première valeur après
x
qui est divisible parz
. Vous pouvez jeterx
:trouver la dernière valeur avant
y
qui est divisible pary
. Vous pouvez jetery
:de trouver la taille de cette gamme:
Si mathématique
floor
etceil
fonctions sont disponibles, les deux premières parties peuvent plus être rédigé lisiblement. En outre, la dernière partie peut être compressé à l'aide de fonctions mathématiques:si l'entrée est la garantie d'une plage valide (
x >= y
), le dernier test oumax
est inutile:(2017, réponse réécrit grâce à des commentaires)
Le nombre de multiples de z dans un certain nombre n est tout simplement
n /z
/
cours de la division entière, sens de décimales qui pourraient résulter de la division sont tout simplement ignorés (par exemple17/5 => 3
et pas3.4
).Maintenant, dans une gamme de x à y, combien multiples de z sont là?
Laisser voir combien de multiples m nous avons jusqu'à y
Vous voyez où je vais... pour obtenir le numéro de multiples dans la gamme
[ x, y ]
, obtenir le nombre de multiples de y puis soustraire le nombre de multiples avant x,(x-1) /z
Solution:
( y /z ) - (( x - 1 ) /z )
Par programme, vous pourriez faire une fonction
numberOfMultiples
pour obtenir le nombre de logements multiples dans une gamme
[x, y]
La fonction est O(1), il n'y a pas besoin d'une boucle pour obtenir le nombre de naissances multiples.
Exemples de résultats, vous devriez trouver
[30, 90] ÷ 13 => 4
[1, 1000] ÷ 6 => 166
[100, 1000000] ÷ 7 => 142843
[777, 777777777] ÷ 7 => 111111001
Pour le premier exemple,
90 /13 = 6
,(30-1) /13 = 2
, et6-2 = 4
x = 6, y = 11, z = 2 { 11 / 2 = 5 => [2, 4, 6, 8, 10] (6 - 1) / 2 = 2 => [2, 4] Answer is 3 => [6, 8, 10] }
J'ai aussi rencontré ce sur Codility. Il m'a fallu beaucoup plus de temps que je le voudrais à admettre pour arriver à une bonne solution, alors j'ai pensé que je voudrais partager ce que je pense est une solution élégante!
Approche Simple 1/2:
O(N) le temps de la solution avec une boucle et de contre, irréaliste quand N = 2 milliards de dollars.
Génial Approche 3:
Nous voulons que le nombre de chiffres dans une certaine gamme qui sont divisibles par K.
Cas Simple: supposons que l'intervalle [0 .. n*K], N = n*K
ex. N = 9, K = 3, Num chiffres = |{0 3 6}| = 3 = 9/3
De même,
ex. N = 9, K = 3, Num chiffres = |{0 3 6 9}| = 4 = 9/3 + 1
Je pense vraiment à comprendre le fait ci-dessus est la partie la plus délicate de cette question, je ne peux pas expliquer exactement pourquoi il fonctionne.
Le reste se résume à préfixe sommes et de manutention des cas particuliers.
Maintenant, nous n'avons pas toujours une gamme qui commence par 0, et nous ne pouvons pas assumer les deux limites sera divisible par K.
Mais attendez! On peut résoudre ce problème par le calcul de notre belle limites supérieure et inférieure, et grâce à la soustraction de la magie 🙂
D'abord trouver le plus proche inférieure et supérieure de l'intervalle [A,B] qui sont divisibles par K.
Puis de calculer le suit, en utilisant la technique ci-dessus:
Calculer le nombre de chiffres entre [A,B] qui sont divisibles par K en temps constant par l'expression X - Y
Site web: https://codility.com/demo/take-sample-test/count_div/
C'est ma première fois d'expliquer une telle approche. La rétroaction est très apprécié 🙂
C'est l'un des Codility Leçon 3 questions. Pour cette question, l'entrée est garanti d'être dans une plage valide. J'ai répondu à l'aide de Javascript:
https://codility.com/demo/results/demoQX3MJC-8AP/
(En fait, je voulais vous demander à propos de certains des autres commentaires sur cette page, mais je n'ai pas assez de points de rep encore).
Diviser
y-x
parz
, arrondi vers le bas. Ajouter un siy%z < x%z
ou six%z == 0
.Pas une preuve mathématique, à moins que quelqu'un se soucie d'en fournir un, mais des cas de test, en Perl:
De sortie:
is
est un multi-manière égale pour les tests unitaires? Aussi, pourquoi puis-je trouvergrep { $_ % $z == 0 } $x..$y
beaucoup moins lisible que, disons,[$x..$y].filter{|$x| $x % $z == 0}
(ruby) ou[$x..$y].filter ($x) => $x % $z == 0
(coffeescript)?is $test_value, $expected, $description
. Comme pour ces derniers, c'est juste ce que vous êtes habitué. Je trouve la coffeescript un quasi-impossible à analyser.Voici mon petit, et la solution la plus simple en C++ qui a 100/100 sur codility. 🙂
S'exécute en O(1) fois. J'espère que sa n'est pas difficile à comprendre.
Laisser
[A;B]
avoir un intervalle d'entiers positifs dont Un et B tels que0 <= A <= B
, K être le diviseur.Il est facile de voir qu'il y a
N(A) = ⌊A /K⌋ = floor(A /K)
facteurs de K dans l'intervalle[0;A]
:De même, il y a
N(B) = ⌊B /K⌋ = floor(B /K)
facteurs de K dans l'intervalle[0;B]
:Puis
N = N(B) - N(A)
est égal au nombre de K's (le nombre d'entiers divisibles par K) dans la gamme(A;B]
. Le point Un n'est pas inclus, parce que le soustraitN(A)
comprend ce point de. Par conséquent, le résultat doit être incrémenté, siA mod K
est égale à zéro:Implémentation en PHP
En PHP, l'effet de la
floor
fonction peut être réalisée par moulage de type integer:qui, je pense, est plus rapide.
Explication:
Il y a un/d nombre divisible par d de 0,0 à un. (d!=0)
Donc (étage)(haut/d) - (étage)(faible/d) pour obtenir les nombres divisibles à la plage (basse,haute] (Notez que faible, est exclue et du haut est inclus dans cette gamme)
Maintenant à retirer à partir de la plage juste soustraire (haute%d==0)
Fonctionne pour les entiers, les décimaux ou que ce soit (Utiliser fmodf fonction de flotteurs)
De ne pas viser un o(1) de la solution, ce congé pour plus personne intelligente:) Juste l'impression que c'est un parfait scénario d'utilisation de la fonction de programmation. Simple et directe.
EDIT: après lecture des autres O(1) solution. Je me sens humiliée. La programmation des gens paresseux pour penser...
Division (a/b=c) par définition, un ensemble de taille et de constituer des groupes de taille b. Le nombre de groupes de cette taille qui peut être formé, c, est le quotient de a et b. - n'est rien de plus que le nombre d'entiers à l'intérieur de la plage/intervalle ]0..a] (pas y compris le zéro, mais y compris) qui sont divisible par b.
donc par définition:
Y/Z - nombre d'entiers dans ]0..Y] qui sont divisible par Z
X/Z - nombre d'entiers dans ]0..X] qui sont divisible par Z
ainsi:
résultat = [Y/Z] - [X/Z] + x (où x = 1 si et seulement si X est divisible par Y sinon 0 - en supposant que l'intervalle donné [X..Y] comprend X)
exemple :
pour (6, 12, 2) nous avons 12/2 - 6/2 + 1 (comme 6%2 == 0) = 6 - 3 + 1 = 4 //{6, 8, 10, 12}
(5, 12, 2) nous avons 12/2 - 5/2 + 0 (comme 5%2 != 0) = 6 - 2 + 0 = 4 //{6, 8, 10, 12}
Le temps de la complexité de la solution sera linéaire.
Extrait De Code :