Öbek - Bir ver


16

Büyük olasılıkla, bu soru daha önce sorulmuştur. CLRS (2. Baskı) probleminden 6.5-8 -

K sıralı listeyi tek bir sıralı listede birleştirmek için zaman algoritması verin ; burada n , tüm giriş listelerindeki toplam öğe sayısıdır. (İpucu: K -yolu birleştirme için bir min-yığın kullanın .)O(nlgk)knk

Bulunmadığından listeleri sıralaması ve toplam n değerleri bize her liste, varsayalım nknÜstelik k sayıları, listelerin her biri kesinlikle artan sırada sıralanır ve sonuçlar da artan sırada depolanır.nk

Sahte kodum şöyle görünüyor -

    list[k]   ; k sorted lists
    heap[k]   ; an auxiliary array to hold the min-heap
    result[n] ; array to store the sorted list
    for i := 1 to k                 ; O(k)
    do
        heap[i] := GET-MIN(list[i]) ; pick the first element 
                                    ; and keeps track of the current index - O(1)
    done
    BUILD-MIN-HEAP(heap) ; build the min-heap - O(k)
    for i := 1 to n
    do
        array[i] := EXTRACT-MIN(heap)   ; store the min - O(logk)
        nextMin := GET-MIN(list[1])     ; get the next element from the list 1 - O(1)
        ; find the minimum value from the top of k lists - O(k)
        for j := 2 to k                 
        do
            if GET-MIN(list[j]) < nextMin
                nextMin := GET-MIN(list[j]) 
        done
        ; insert the next minimum into the heap - O(logk)
        MIN-HEAP-INSERT(heap, nextMin)
    done

Genel karmaşıklığım . O ( n ) içindeki O ( k ) döngüsünü önlemek için herhangi bir yol bulamadımO(k)+O(k)+O(n(k+2lgk))O(nk+nlgk)O(nk)O(k)O(n)k listelerinden bir sonraki minimum öğeyi bulmak için döngü. Başka bir yol var mı? Nasıl bir olsun algoritması?O(nlgk)

Yanıtlar:


14

Yığın amacı size minimum vermek, bu yüzden bu for-loop'un amacının ne olduğundan emin değilim for j := 2 to k.

Sahte kod almam:

lists[k][?]      // input lists
c = 0            // index in result
result[n]        // output
heap[k]          // stores index and applicable list and uses list value for comparison
                 // if i is the index and k is the list
                 //   it has functions - insert(i, k) and deleteMin() which returns i,k
                 // the reason we use the index and the list, rather than just the value
                 //   is so that we can get the successor of any value

// populate the initial heap
for i = 1:k                   // runs O(k) times
  heap.insert(0, k)           // O(log k)

// keep doing this - delete the minimum, insert the next value from that list into the heap
while !heap.empty()           // runs O(n) times
  i,k = heap.deleteMin();     // O(log k)
  result[c++] = lists[k][i]
  i++
  if (i < lists[k].length)    // insert only if not end-of-list
    heap.insert(i, k)         // O(log k)

O(klogk+n2logk)=O(nlogk)

deleteMininsertgetMinO(1)incrementIndexO(logk)

Örnek:
(açıklık için sıralı dizi olarak temsil edilen dizin ve liste dizini ve yığın yerine değer kullanma)

Input: [1, 10, 15], [4, 5, 6], [7, 8, 9]

Initial heap: [1, 4, 7]

Delete 1, insert 10
Result: [1]
Heap: [4, 7, 10]

Delete 4, insert 5
Result: [1, 4]
Heap: [5, 7, 10]

Delete 5, insert 6
Result: [1, 4, 5]
Heap: [6, 7, 10]

Delete 6, insert nothing
Result: [1, 4, 5, 6]
Heap: [7, 10]

Delete 7, insert 8
Result: [1, 4, 5, 6, 7]
Heap: [8, 10]

Delete 8, insert 9
Result: [1, 4, 5, 6, 7, 8]
Heap: [9, 10]

Delete 9, insert nothing
Result: [1, 4, 5, 6, 7, 8, 9]
Heap: [10]

Delete 10, insert 15
Result: [1, 4, 5, 6, 7, 8, 9, 10]
Heap: [15]

Delete 15, insert nothing
Result: [1, 4, 5, 6, 7, 8, 9, 10, 15]
Heap: []

Done

diyelim ki birleştirmek için bu listeler var, liste [1] = [1, 10, 15], liste [2] = [4, 5, 6] ve liste [3] = [7, 8, 9]. İlk yinelemede, öbekteki değer 1 olacak ve daha sonra algoritmanız yığına 10 ekleyecektir, ancak 10 tüm listelerin en büyük değeridir - bundan nasıl kaçınacaksınız?
ramgorur

@ramgorur 10'un yığınta olması önemli değil. 4,5,6,7,8 ve 9, her zaman yığından en küçük değeri aldığımızdan ve silinen değerleri aynı listeden bir sonraki öğeyle değiştirmeye devam ettiğimizden önce işlenecektir. Örnek ile cevap düzenlendi.
Dukeling

eğer durum buysa, bir sonraki eleman itme için aynı listeyi hatırlamamız gerekmiyor . Her seferinde rastgele bir liste seçebilir ve bir sonraki elemanı yığın haline getirebiliriz - ki bu da aynı sonucu verecektir, doğru mu? Yoksa aynı liste argümanını takip etmenin başka özel bir nedeni var mı?
ramgorur

Silerken 4, rastgele bir liste seçerseniz, ekleme işlemi sona erebilir 8, bu nedenle yığın , sonuç kümesinin yerine [7, 8, 10]ekleyeceğiniz yanlış olur. 75
Dukeling

O(k)

13

n/k

Sorununuza gelince, aşağıdaki algoritma hile yapmalıdır:

  1. HklmO(klgk)
  2. i1n
    • mHresult[i]O(lgk)
    • mlmHO(lgk)

O(klgk+nlgk)=O(nlgk)result

iresultHiresult[1..i]i

resultHresultr1lr1l[1]r1r1l[1]<r1r1result

iriHHmllHresultrimll

result[1..n]


Aslında daha sıkı zaman karmaşıklığı O (K + 2 * NlogK) = O (NlogK) olacaktır . O (K), bir Öbek yaparken O (KlogK) 'dan daha sıkı bağlanır . Bakın bu başka açıklamalar için.
Ashwani Gautam

O(k)O(klogk)k
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.