Aggressive Cows
Une grange comporte des stalles alignées sur une seule ligne droite, et stalls[i] est la position de la stalle i. Les positions sont toutes différentes et ne suivent aucun ordre particulier. Vous devez placer k vaches dans k stalles différentes, et les vaches se battent lorsqu'elles sont proches les unes des autres ; vous voulez donc que les deux vaches les plus proches soient aussi éloignées que possible.
Retournez la plus grande valeur possible de la distance minimale entre deux vaches quelconques.
Fonction
- stallsinteger-array
- les positions distinctes des stalles, dans n’importe quel ordre
- kinteger
- le nombre de vaches à placer
- Renvoieinteger
- la plus grande distance minimale possible entre deux vaches
Contraintes
2 ≤ stalls.length ≤ 50000 ≤ stalls[i] ≤ 109- Toutes les positions dans
stallssont distinctes. 2 ≤ k ≤ stalls.length
Exemples
- Entrée
- stalls = [10, 1, 7, 4, 15]k = 3
- Sortie
- 6
- Explication
- Les vaches placées en 1, 7 et 15 sont séparées par 6 puis 8. Une distance de 7 ne convient pas : après 1, la vache suivante est placée en 10, et aucun emplacement ne se trouve en 17 ou au-delà.
- Entrée
- stalls = [9, 3, 20, 5]k = 4
- Sortie
- 2
- Explication
- Quatre vaches et quatre étables signifient que chaque étable reçoit une vache. En les triant, les étables sont 3, 5, 9 et 20, et les voisines les plus proches, 3 et 5, sont séparées de 2.
- Entrée
- stalls = [14, 2, 30, 22, 8]k = 2
- Sortie
- 28
- Explication
- Deux vaches sont mieux placées aux deux extrémités de la ligne. Les stalles vont de 2 à 30, les vaches sont donc séparées de 28.
Pour aller plus loin
Qu’est-ce qui change si les stands sont disposés en cercle, de sorte que le dernier stand dans l’ordre soit également voisin du premier ?
Indices
Ouvrez-les un par un. Chacun en dévoile un peu plus.
Mettons de côté la meilleure réponse un instant. Si quelqu’un te donne un écart
g, peux-tu déterminer sikvaches peuvent être placées de sorte que chacune soit séparée des autres d’au moinsg?Triez les stalles et placez les vaches en partant de la gauche, chacune dans la première stalle située au moins à
gde la vache précédente. Si un écart convient, tous les écarts plus petits conviennent aussi.Effectuez une recherche binaire de
gentre 1 et l’étendue des emplacements divisée park-1. Conservez le plus grand écart pour lequel l’algorithme glouton place au moinskvaches.
Solution
Fixe un écart et demande-toi : est-ce que k vaches peuvent se tenir en étant toutes séparées d’au moins cette distance ? Un passage glouton sur les stalles triées permet de répondre. La réponse passe de oui à non une seule fois à mesure que l’écart augmente, donc la recherche binaire trouve le dernier oui.
Trier, puis essayer chaque intervalle à tour de rôle
Correcte, mais ne termine pas sur les plus gros tests
Intuition
Triez les positions. Les deux vaches les plus proches sont alors toujours voisines, donc un écart g convient lorsque chaque paire de vaches voisines est séparée d’au moins g.
Pour tester un écart, placez une vache dans l’enclos le plus à gauche, puis une autre dans chaque enclos situé à au moins g de la dernière vache. Ce placement glouton permet de placer autant de vaches que n’importe quel autre placement. Alignez n’importe quel placement valide en partant de la gauche : la vache i du placement glouton n’est jamais à droite de la vache i de cet autre placement, donc le placement glouton trouve un enclos pour sa vache suivante au plus tard.
Un écart de 1 convient toujours, alors essayez g = 2, 3, ... et arrêtez-vous au premier écart qui permet de placer moins de k vaches. Dans le premier exemple, un écart de 6 permet de placer 3 vaches et un écart de 7 seulement 2, donc la réponse est 6.
Avec deux vaches et des enclos aux positions 0 et 10^9, cela représente environ 10^9 parcours de 5000 enclos, soit 5 × 10^12 étapes.
Algorithme
- Trie les positions.
- Écris la vérification pour un écart
g: une vache àpos[0], puis une vache dans chaque étable oùpos[i] - last ≥ g, en comptant les vaches. - Commence avec
gap = 1. - Tant que la vérification pour
gap + 1permet de placer au moinskvaches, ajoute 1 àgap. - Retourne
gap.
def cowsPlaced(pos, gap):
count, last = 1, pos[0] # the first cow takes the leftmost stall
for p in pos[1:]:
if p - last >= gap:
count += 1
last = p
return count
def aggressiveCows(stalls, k):
pos = sorted(stalls)
gap = 1 # positions are distinct, so a gap of 1 always fits every cow
while cowsPlaced(pos, gap + 1) >= k:
gap += 1
return gapRecherche dichotomique sur l’écart
Intuition
Un placement où chaque écart est d’au moins g+1 a également chaque écart d’au moins g, les résultats des tests sont donc oui, ..., oui, non, ..., non. La recherche binaire trouve le dernier oui.
Commencez la recherche avec lo = 1, qui fonctionne toujours, jusqu’à hi = l’étendue divisée par k-1, arrondie à l’entier inférieur : k vaches laissent k-1 écarts dans l’étendue, le plus petit ne peut donc pas être supérieur. Un test réussi définit lo = mid, donc mid doit être arrondi à l’entier supérieur ; arrondis à l’entier inférieur, lo = 5 et hi = 6 se répètent à l’infini.
Dans le premier exemple, l’étendue est de 14 et k = 3, donc hi = 7. Un écart de 4 est accepté, un écart de 6 est accepté, un écart de 7 échoue et l’intervalle se referme sur 6.
Un intervalle d’une largeur allant jusqu’à 10^9 se referme en environ 30 tests portant sur 5000 stalles, soit environ 150 000 étapes.
Algorithme
- Trie les positions.
- Définis
lo = 1ethi = (pos[n-1] - pos[0]) / (k-1), arrondi à l’entier inférieur. - Tant que
lo < hi, prendsmid = lo + (hi - lo + 1) / 2. - Si la vérification gloutonne à
midpermet de placer au moinskvaches, définislo = mid; sinon, définishi = mid - 1. - Renvoie
lo.
def cowsPlaced(pos, gap):
count, last = 1, pos[0] # the first cow takes the leftmost stall
for p in pos[1:]:
if p - last >= gap:
count += 1
last = p
return count
def aggressiveCows(stalls, k):
pos = sorted(stalls)
lo = 1 # positions are distinct, so a gap of 1 always works
hi = (pos[-1] - pos[0]) // (k - 1) # k-1 gaps share the whole span
while lo < hi:
mid = lo + (hi - lo + 1) // 2 # round up so lo = mid always moves
if cowsPlaced(pos, mid) >= k:
lo = mid # mid fits, so the answer is mid or larger
else:
hi = mid - 1 # mid does not fit, so the answer is smaller
return lo
Pièges et cas limites
- Ignorer le tri. Dans la liste non triée
[10, 1, 7, 4, 15]avec un écart de 6, la vérification commence à 10, ne trouve aucune étable ultérieure située au moins 6 unités plus loin et indique qu’il y a une vache. - Arrondir
midvers le bas alors qu’une passe définitlo = mid. Une fois quehi = lo + 1, l’intervalle cesse de rétrécir et la boucle ne se termine jamais. - Vérifier qu’il y a exactement
kvaches. Avec un écart de 1, le premier exemple place 5 vaches, soit plus que 3, et l’écart convient pourtant ; vérifiezcount ≥ k. - Commencer le décompte des vaches à 0. La vache dans l’étable la plus à gauche compte, donc le décompte commence à 1.
Questions fréquentes3
Quelle est la complexité temporelle d’Aggressive Cows ?
Le tri prend O(n log n) et la recherche binaire O(n log D), où D est l’étendue des emplacements divisée par k-1. En plus d’une copie triée, la mémoire utilisée est de O(1).
Pourquoi la première vache va-t-elle toujours dans l'étable la plus à gauche ?
Prenez n’importe quel placement qui fonctionne et déplacez sa vache la plus à gauche vers l’écurie la plus à gauche. Cette vache ne fait que s’éloigner des autres, donc aucune distance ne diminue, et un placement optimal utilise l’écurie la plus à gauche.
Comment repérer une recherche binaire sur la réponse ?
La question demande la plus grande ou la plus petite valeur pour laquelle quelque chose est possible. Vérifier une valeur est beaucoup plus facile que trouver la meilleure, et les réponses ne changent qu’une seule fois à mesure que la valeur augmente. Ici, la valeur est l’écart et la vérification consiste à effectuer le placement glouton.
Problèmes similaires
Des problèmes qui reposent sur les mêmes idées. En résoudre deux ou trois, c’est ce qui ancre un schéma.
def aggressiveCows(stalls, k):
# Écrivez le code iciTest #1
Test #2
Test #3
Arguments
stalls = [10, 1, 7, 4, 15] k = 3
Résultat attendu
6