Aggressive Cows
Bir ahırda tek bir düz çizgi boyunca ahır bölmeleri bulunur ve stalls[i], i. bölmenin konumudur. Konumların hepsi farklıdır ve belirli bir sırada verilmemiştir. k ineği k farklı bölmeye yerleştirmelisin. İnekler birbirine yakın durduklarında kavga eder; bu yüzden birbirine en yakın iki ineği olabildiğince uzağa yerleştirmek istiyorsun.
Herhangi iki inek arasındaki en küçük mesafenin alabileceği en büyük değeri döndür.
Fonksiyon
- stallsinteger-array
- birbirinden farklı durak konumları, herhangi bir sırada
- kinteger
- yerleştirilecek inek sayısı
- Döndürürinteger
- iki inek arasındaki mümkün olan en büyük en küçük mesafe
Kısıtlar
2 ≤ stalls.length ≤ 50000 ≤ stalls[i] ≤ 109- Tüm
stallskonumları birbirinden farklıdır. 2 ≤ k ≤ stalls.length
Örnekler
- Girdi
- stalls = [10, 1, 7, 4, 15]k = 3
- Çıktı
- 6
- Açıklama
- 1, 7 ve 15 numaralı ahırlardaki inekler arasında sırasıyla 6 ve 8 birim mesafe vardır. 7 birimlik aralık işe yaramaz: 1'den sonra sıradaki inek 10'a yerleşir ve 17'de veya daha ileride hiçbir ahır yoktur.
- Girdi
- stalls = [9, 3, 20, 5]k = 4
- Çıktı
- 2
- Açıklama
- Dört inek ve dört ahır, her ahıra bir inek düşmesi demektir. Sıralandığında ahırlar 3, 5, 9 ve 20 olur ve en yakın komşular olan 3 ile 5 arasında 2 fark vardır.
- Girdi
- stalls = [14, 2, 30, 22, 8]k = 2
- Çıktı
- 28
- Açıklama
- İki inek, sıranın iki ucunda en iyi konumdadır. Ahırlar 2'den 30'a kadar sıralanır, bu yüzden inekler arasında 28 birim vardır.
Ek soru
Tezgâhlar bir daire üzerinde durursa ne değişir; böylece sıradaki son tezgâh, ilk tezgâhın da komşusu olur?
İpuçları
Tek tek açın. Her biri biraz daha fazlasını gösterir.
En iyi yanıtı bir anlığına bir kenara bırak. Biri sana
garalığını verirse,kineğin her ikisi arasında en azgmesafe olacak şekilde sığıp sığmayacağına karar verebilir misin?Ahırları sırala ve inekleri soldan başlayarak, her birini önceki inekten en az
guzaklıktaki ilk ahıra yerleştir. Bir aralık uygunsa, daha küçük her aralık da uygundur.Ahırların aralığı ile
k-1değerinin bölümünü üst sınır alarak 1 ile bu değer arasındagiçin ikili arama yapın. Açgözlü yerleştirme yönteminin en azkinek yerleştirdiği en büyük aralığı koruyun.
Çözüm
Bir aralık belirleyip şunu sor: Her iki ineğin arasında en az bu kadar mesafe olacak şekilde k inek yerleştirilebilir mi? Sıralanmış ahırlar üzerinde yapılacak tek bir açgözlü geçiş bu soruyu yanıtlar. Aralık büyüdükçe yanıt bir kez evetten hayıra döner; bu yüzden ikili arama son evet değerini bulur.
Sırala, ardından her boşluğu sırayla dene
Doğru, ama en büyük testlerde bitmiyor
Sezgi
Konumları sırala. En yakın iki inek her zaman komşu olur; bu nedenle komşu ineklerin arasındaki mesafe en az g olduğunda g aralığı geçerlidir.
Bir aralığı sınamak için en soldaki bölmeye bir inek, ardından da son ineğin en az g ötesindeki her bölmeye bir inek yerleştir. Bu açgözlü yerleştirme, mümkün olan tüm yerleştirmeler arasında en fazla sayıda ineği sığdırır. Geçerli herhangi bir yerleştirmeyi soldan hizala: açgözlü yerleştirmedeki i. inek, o yerleştirmedeki i. ineğin asla sağında olmaz; bu yüzden açgözlü yöntem bir sonraki ineği en geç o ineğin yerleştirildiği bölmeye yerleştirebilir.
1 aralığı her zaman geçerlidir; bu yüzden g = 2, 3, ... değerlerini dene ve ilk olarak k inekten daha azını yerleştiren aralıkta dur. İlk örnekte 6 aralığı 3 inek, 7 aralığı ise yalnızca 2 inek yerleştirir; dolayısıyla yanıt 6'dır.
İki inek ve 0 ile 10^9 konumlarında bölmeler olduğunda, 5000 bölme üzerinde yaklaşık 10^9 geçiş, yani 5 × 10^12 adım gerekir.
Algoritma
- Konumları sıralayın.
garalığı için kontrolü yazın:pos[0]konumunda bir inek, ardındanpos[i] - last ≥ gkoşulunu sağlayan her ahırda bir inek olacak şekilde inekleri sayın.gap = 1ile başlayın.gap + 1için yapılan kontrol en azkinek yerleştiriyorsagapdeğerini 1 artırın.gapdeğerini döndürün.
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 gapAralıkta ikili arama
Sezgi
Her boşluğu en az g+1 olan bir yerleşimde, her boşluk en az g de olur; bu nedenle kontroller evet, ..., evet, hayır, ..., hayır şeklindedir. İkili arama son eveti bulur.
Her zaman işe yarayan lo = 1 değerinden başlayıp hi değerini aralığın k-1'e bölünüp aşağı yuvarlanmış hâli olarak belirleyin: k inek, aralığın içinde k-1 boşluk bırakır; dolayısıyla en küçük boşluk bundan büyük olamaz. Kontrol başarılı olursa lo = mid olarak ayarlanır; bu yüzden mid yukarı yuvarlanmalıdır. Aşağı yuvarlanırsa lo = 5 ve hi = 6 sonsuza kadar tekrarlanır.
İlk örnekte aralık 14 ve k = 3 olduğundan hi = 7 olur. Boşluk 4 başarılıdır, boşluk 6 başarılıdır, boşluk 7 başarısızdır ve aralık 6'da kapanır.
10^9 genişliğe kadar olan bir aralık yaklaşık 5000 ahır bölmesi üzerinde 30 kontrolde kapanır; bu da kabaca 150.000 adımdır.
Algoritma
- Konumları sırala.
lo = 1vehi = (pos[n-1] - pos[0]) / (k-1)değerlerini ayarla; aşağı yuvarla.lo < hiolduğu sürecemid = lo + (hi - lo + 1) / 2değerini al.middeğerindeki açgözlü kontrol en azkinek yerleştiriyorsalo = midolarak ayarla; aksi hâldehi = mid - 1olarak ayarla.lodeğerini döndür.
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
Tuzaklar ve uç durumlar
- Sıralamayı atlamak. Sıralanmamış
[10, 1, 7, 4, 15]dizisinde, aralık 6 iken kontrol 10'dan başlar, ondan 6'dan daha uzakta başka bir ahır bulamaz ve bir inek olduğunu bildirir. - Bir geçiş sırasında
lo = midatanırkenmiddeğerini aşağı yuvarlamak.hi = lo + 1olduktan sonra aralık küçülmeyi durdurur ve döngü hiç bitmez. - Tam olarak
kinek olup olmadığını kontrol etmek. Aralık 1 iken ilk örnekte 5 inek yerleştirilir; bu sayı 3'ten fazladır, ancak aralık işe yarar.count ≥ kkoşulunu kontrol et. - İnek sayısını 0'dan başlatmak. En soldaki ahırdaki inek de sayılır, bu yüzden sayaç 1'den başlar.
Sıkça sorulan sorular3
Aggressive Cows'un zaman karmaşıklığı nedir?
Sıralama O(n log n), ikili arama ise O(n log D) zaman alır; burada D, ahırların kapladığı aralığın k-1'e bölünmesiyle elde edilir. Sıralanmış bir kopya dışında bellek kullanımı O(1)'dir.
İlk inek neden her zaman en soldaki ahıra girer?
İşe yarayan herhangi bir yerleşimi al ve en soldaki ineğini en soldaki bölmeye taşı. Bu inek yalnızca diğerlerinden uzaklaşır; dolayısıyla hiçbir mesafe kısalmaz ve en iyi yerleşimlerden biri en soldaki bölmeyi kullanır.
Cevap üzerinde ikili aramayı nasıl fark edersiniz?
Soru, bir şeyin mümkün olduğu en büyük veya en küçük değeri soruyor; tek bir değeri kontrol etmek, en iyisini bulmaktan çok daha kolay ve değer arttıkça yanıtlar yalnızca bir kez değişiyor. Burada değer aralık, kontrol ise açgözlü yerleştirmedir.
Benzer problemler
Aynı fikirleri kullanan problemler. İki üçünü çözmek bir kalıbı kalıcı hale getirir.
def aggressiveCows(stalls, k):
# Kodu buraya yazınTest #1
Test #2
Test #3
Argümanlar
stalls = [10, 1, 7, 4, 15] k = 3
Beklenen Çıktı
6