Range Sum of BST
İkili arama ağacı, dizi tree içinde seviye sırasıyla saklanır: kök 0 indeksindedir, i indeksindeki düğümün çocukları 2*i+1 (sol) ve 2*i+2 (sağ) indekslerindedir ve boş bir yeri -1 belirtir. İkili arama ağacında, bir düğümün sol alt ağacındaki her değer düğümün değerinden küçüktür, sağ alt ağacındaki her değer ise düğümün değerinden büyüktür.
low ≤ v ≤ high koşulunu sağlayan tüm düğüm değerlerinin v toplamını döndür; böyle bir değer yoksa 0 döndür.
Fonksiyon
- treeinteger-array
- ikili arama ağacını seviye sırasına göre, boş bir konum için -1 kullanarak
- lowinteger
- sayılacak en küçük değer
- highinteger
- sayılacak en büyük değer
- Döndürürinteger
- düşük ve yüksek değerleri de dâhil olmak üzere, aralarındaki düğüm değerlerinin toplamı
Kısıtlar
1 ≤ tree.length ≤ 32767- Her
tree[i],-1ya da0 ≤ tree[i] ≤ 105koşulunu sağlayan bir değerdir. tree[0]hiçbir zaman-1değildir, dolayısıyla ağacın en az bir düğümü vardır.- Dizi, son düğümden sonra fazladan
-1girdileri içerebilir. - Boş bir noktanın her iki çocuğu da boştur ve derinlik en fazla
14olur. - Ağaç geçerli bir ikili arama ağacıdır, bu nedenle tüm değerleri birbirinden farklıdır.
0 ≤ low ≤ high ≤ 105- Yanıt, 32 bitlik işaretli bir tamsayıya sığar.
Örnekler
- Girdi
- tree = [20, 8, 31, 3, 12, -1, 40, -1, -1, 10, 15]low = 9high = 31
- Çıktı
- 88
- Açıklama
9ile31arasındaki değerler10,12,15,20ve31'dir; bunların toplamı88eder.3,8ve40aralığın dışındadır.
- Girdi
- tree = [50, 25, 75, -1, -1, -1, -1]low = 60high = 70
- Çıktı
- 0
- Açıklama
- Ağaç
25,50ve75değerlerini içerir ve bunların hiçbiri60ile70arasında değildir; bu nedenle toplam0olur. Dört-1girdisi,25ve75düğümlerinin boş çocuk konumlarıdır.
- Girdi
- tree = [6, 2, 9, 1, 4, 7]low = 4high = 4
- Çıktı
- 4
- Açıklama
lowvehighdeğerleri4olduğunda, yalnızca değeri4olan bir düğüm sayılır.4indisindeki4,2düğümünün sağ çocuğudur; dolayısıyla yanıt4olur.
Ek soru
Aynı ağaç üzerinde binlerce farklı (low, high) sorgusunu yanıtlamanız gerekseydi, her birini O(log n) sürede nasıl yanıtlayabilirdiniz?
İpuçları
Tek tek açın. Her biri biraz daha fazlasını gösterir.
Her düğümü ziyaret edip aralıktaki değerleri toplamak doğru yanıtı verir. Arama ağacının sıralaması, bir düğümün altındaki değerler hakkında sana ne söyler?
Bir düğümün sol alt ağacındaki her şey düğümden küçüktür ve sağ alt ağacındaki her şey düğümden büyüktür. Düğümün değeri en fazla
lowise solundaki herhangi bir şey aralıkta olabilir mi?Kökten başlayarak indekslerden oluşan bir yığınla ağacı dolaşın. Bir düğümün değeri aralık içindeyse bu değeri ekleyin; sol çocuğunu yalnızca değer
low'dan büyük olduğunda2*i+1indeksine, sağ çocuğunu ise yalnızca değerhigh'dan küçük olduğunda2*i+2indeksine yığına ekleyin.
Çözüm
Her düğümü ziyaret etmek ve aralıktaki değerleri toplamak doğrudur. Arama ağacının sıralaması daha az işlem yapmanı sağlar: Bir düğümün değeri, küçük ve büyük değerlerin hangi tarafta olduğunu gösterir; böylece aralığa ulaşamayacak bir alt ağaç hiç açılmaz.
Her düğümü ziyaret et
Sezgi
Bir çocuk, yalnızca dizideki indeksi mevcutsa ve oradaki değer -1 değilse gerçektir. İlk örnekte, 4 indeksindeki 12'nin 9 ve 10 indekslerinde 10 ve 15 değerleri vardır; 2 indeksindeki 31'in ise 5 indeksinde boş bir sol yeri vardır.
Aralıktaki her değer bir düğümde bulunduğundan, her düğüme ulaşan ve low ≤ v ≤ high koşulunu sağlayan değerleri toplayan bir yığın dolaşımı doğru toplamı verir. Arama ağacının sırasını göz ardı ettiğinden, aralıkta yalnızca birkaç değer olsa bile n düğümün tümüne dokunur.
Algoritma
- Kök dizin
0değerini yığına ekleyin vetotal = 0olarak ayarlayın. - Bir
idizinini yığından çıkarın.low ≤ tree[i] ≤ highisetree[i]değerinitotaldeğerine ekleyin. - Dizi sınırları içindeyse ve
-1değilse2*i+1ve2*i+2değerlerini yığına ekleyin. - Yığın boşaldığında
totaldeğerini döndürün.
def rangeSumBST(tree, low, high):
n = len(tree)
total = 0
stack = [0] # node indexes still to visit; the root is never empty
while stack:
i = stack.pop()
value = tree[i]
if low <= value <= high:
total += value
left, right = 2 * i + 1, 2 * i + 2
if left < n and tree[left] != -1:
stack.append(left)
if right < n and tree[right] != -1:
stack.append(right)
return totalArama ağacı sırasına göre budama
Sezgi
v değerini tutan bir düğümün sol alt ağacında yalnızca v değerinden küçük değerler bulunur. v ≤ low ise bunların hiçbiri aralıkta değildir; bu nedenle bu alt ağacı atla. v ≥ high ise sağ alt ağaçta yalnızca high değerinden büyük değerler bulunur; bu nedenle onu atla. İlk örnekte 31, high değerine eşittir; bu yüzden sağ çocuğu 40 hiçbir zaman yığına eklenmez. 8, low değerinden küçüktür; bu nedenle sol çocuğu 3 atlanır, ancak 8 ile 20 arasındaki değerler aralıkta olabileceği için sağ çocuğu 12 ziyaret edilir.
Aralıktaki k değeri ve kökten başlayan en fazla iki yol üzerindeki düğümleri ziyaret edersin: derinlik h için O(h + k) zaman. Aralık ağacın tamamını kapsadığında bile bu süre O(n) olur.
Algoritma
- Kök indeksini
0yığına ekleyin vetotal = 0olarak ayarlayın. - Yığından
iindeksini çıkarın vev = tree[i]değerini okuyun.low ≤ v ≤ highisevdeğerinitotaldeğerine ekleyin. v > lowise, gerçek olduğu durumda sol çocuk2*i+1değerini yığına ekleyin.v < highise, gerçek olduğu durumda sağ çocuk2*i+2değerini yığına ekleyin.- Yığın boş olduğunda
totaldeğerini döndürün.
def rangeSumBST(tree, low, high):
n = len(tree)
total = 0
stack = [0] # node indexes still to visit; the root is never empty
while stack:
i = stack.pop()
value = tree[i]
if low <= value <= high:
total += value
left, right = 2 * i + 1, 2 * i + 2
# Smaller values sit on the left, larger on the right: skip a side the range cannot reach.
if value > low and left < n and tree[left] != -1:
stack.append(left)
if value < high and right < n and tree[right] != -1:
stack.append(right)
return total
Tuzaklar ve uç durumlar
- Katı karşılaştırmalar kullanmak. Her iki uç da dahildir; bu nedenle
low = high = 4olan üçüncü örnekte4sayılmalıdır. - Bir adım çok erken budamak.
v = lowolduğunda sol alt ağaç elenebilir; ancakv = low + 1olduğunda bu alt ağaçtalowdeğerinin kendisi bulunabilir. - Aralığın dışındaki bir düğümün iki tarafını da elemek. İlk örnekteki
8,lowdeğerinden küçüktür; ancak sağ alt ağacında10,12ve15bulunur. - Dizinin sonunu aşan bir çocuğu okumak. Okumadan önce
2*i+1 < tree.lengthkoşulunu kontrol edin ve-1değerini çocuk olmadığı şeklinde değerlendirin. - Lua ve R'de diziler 1'den başlar:
2*i+1aritmetiği için düğüm indekslerini 0 tabanlı tutun vetree[i + 1]öğesini okuyun.
Sıkça sorulan sorular3
BST Aralık Toplamı'nın zaman karmaşıklığı nedir?
Budanmış dolaşım, aralıktaki k düğümü ve kökten başlayan en fazla iki yol üzerindeki düğümleri ziyaret eder: derinliği h olan bir ağaç için O(h + k) zaman, tüm değerler aralıkta olduğunda ise O(n) zaman alır. Yığın veya özyineleme O(h) alan kullanır.
BST'nin Aralık Toplamı, sıralı dolaşım kullanılarak çözülebilir mi?
Evet. Sıralı dolaşım değerleri artan sırada listeler; bu nedenle değerler low değerine ulaştığında onları eklersin ve high değerinden büyük olan ilk değerde durursun. Erken durmak ağacın sağ tarafındaki işi azaltır; budama ise her iki taraftaki işi azaltır.
BST'nin Aralık Toplamı için özyineleme mi yoksa yığın mı kullanmalısınız?
İkisi de işe yarar. Burada derinlik en fazla 14 olduğundan özyineleme sığ kalır. Açık bir yığın, binlerce seviyeli uzun bir ağaçta özyineleme sınırına takılmayı önler.
Benzer problemler
Aynı fikirleri kullanan problemler. İki üçünü çözmek bir kalıbı kalıcı hale getirir.
def rangeSumBST(tree, low, high):
# Kodu buraya yazınTest #1
Test #2
Test #3
Argümanlar
tree = [20, 8, 31, 3, 12, -1, 40, -1, -1, 10, 15] low = 9 high = 31
Beklenen Çıktı
88