Ön Ek Toplamları ve Birikimli Toplamlar
O(1) sürede aralık toplamı sorgularını yanıtlamak için ön ek toplam dizileri oluşturun ve bu tekniği maksimum toplamlı alt dizi gibi alt dizi problemlerine uygulayın.
Ön Ek Toplamları ve Birikimli Toplamlar, CoddyKit'te ücretsiz bir DSA Interview Prep dersidir. Bu, 4 dersinin 2. dersidir. Aşağıdan dersin tamamını ücretsiz okuyabilir, sonra tarayıcıda yerleşik kod editörü ve 7/24 yapay zeka koçu ile uygulamalı olarak pratik yapabilirsin. Bu, DSA Interview Prep öğrenme yolunun bir parçasıdır ve ilerlemeniz web ve CoddyKit uygulaması arasında senkronize olur. DSA Interview Prep kursu toplamda 4 dersten oluşur.
Aralık Toplamı Problemi
nums dizisi verildiğinde, şu biçimdeki çok sayıda sorguyu yanıtlamanız gerekir: i dizininden j dizinine kadar olan öğelerin toplamı nedir? Her sorguyu naif biçimde hesaplamak O(n) zaman alır; bu nedenle k sorgusu O(n×k) maliyetlidir. Bir önek toplamı dizisi ile O(n) zamanda kümülatif bir toplamı önceden hesaplar ve ardından her sorguyu O(1) zamanda yanıtlarsınız. Bu, mülakatlarda en yaygın kullanılan ön hesaplama tekniklerinden biridir.
# Naive: O(n) per query
def range_sum_naive(nums, i, j):
return sum(nums[i:j+1])
nums = [1, 3, 5, 7, 9]
print(range_sum_naive(nums, 1, 3)) # 3+5+7 = 15
print(range_sum_naive(nums, 0, 4)) # 1+3+5+7+9 = 25
# For 1000 queries, this takes 5000 operationsÖnek Toplamı Dizisini Oluşturma
prefix[i] değerini, nums[0] ile nums[i-1] arasındaki öğelerin toplamı olarak tanımlayın (bir ek yuva kullanılır; 1 ofsetli sıfır tabanlı dizinleme, sınır durumlarını daha anlaşılır hâle getirir). Diziyi tek geçişte O(n) zamanda oluşturun: prefix[i] = prefix[i-1] + nums[i-1]. Ardından bir aralık sorgusu olan sum(i, j), O(1) maliyetli tek bir çıkarma işlemiyle prefix[j+1] - prefix[i] hâline gelir.
def build_prefix(nums):
n = len(nums)
prefix = [0] * (n + 1)
for i in range(n):
prefix[i+1] = prefix[i] + nums[i]
return prefix
def range_sum(prefix, i, j):
return prefix[j+1] - prefix[i] # O(1)
nums = [1, 3, 5, 7, 9]
pre = build_prefix(nums)
print(pre) # [0, 1, 4, 9, 16, 25]
print(range_sum(pre, 1, 3)) # 9 - 1 = 8? Wait: 3+5+7=15
# Hmm: prefix[4]-prefix[1] = 16-1 = 15 correct
print(range_sum(pre, 1, 3)) # 15Alt Dizi Toplamı K'ye Eşit
Toplamı k'ye eşit olan alt dizilerin sayısını bulmak, klasik bir karma harita + önek toplamı problemidir. Temel fikir şudur: i ile j arasındaki alt dizi toplamı prefix[j] - prefix[i-1] değerine eşittir. Bunun k'ye eşit olmasını istiyorsak prefix[i-1] = prefix[j] - k olmalıdır. Soldan sağa tararken kümülatif önek toplamını tutar, daha önce current_sum - k değerinin kaç kez görüldüğüne bakar ve tüm geçerli alt dizileri toplam O(n) zamanda sayarız.
from collections import defaultdict
def subarray_sum_k(nums, k):
count = 0
current = 0
freq = defaultdict(int)
freq[0] = 1 # empty prefix
for n in nums:
current += n
count += freq[current - k] # how many prior sums give diff=k
freq[current] += 1
return count
print(subarray_sum_k([1, 1, 1], 2)) # 2
print(subarray_sum_k([1, 2, 3], 3)) # 2 ([1,2] and [3])Önek Toplamıyla Maksimum Alt Dizi Toplamı
Maksimum alt dizi toplamı, bir önek toplamı problemi olarak ifade edilebilir: her j dizini için, tüm i < j değerleri arasında prefix[j] - prefix[i] ifadesini en büyüklemek isteriz. Her j için en iyi i, şimdiye kadar görülen en küçük önek toplamıdır. Soldan sağa tararken min_prefix değerini izlemek O(n) zaman alır. Bu, önek toplamı açısından yorumlanan Kadane algoritmasıyla eşdeğerdir.
def max_subarray_prefix(nums):
max_sum = float('-inf')
min_pre = 0 # prefix[0] = 0
current = 0
for n in nums:
current += n
max_sum = max(max_sum, current - min_pre)
min_pre = min(min_pre, current)
return max_sum
print(max_subarray_prefix([-2,1,-3,4,-1,2,1,-5,4]))
# 6 (same as Kadane's)
print(max_subarray_prefix([-1,-2,-3]))
# -1Izgara Sorguları için 2B Önek Toplamları
Önek toplamları 2B ızgaralara da genişletilebilir. P[i][j] değerini, (0,0) ile (i-1,j-1) arasındaki dikdörtgende bulunan tüm öğelerin toplamı olarak tanımlayın. Diziyi kapsama-dışlama formülüyle oluşturun: P[i][j] = P[i-1][j] + P[i][j-1] - P[i-1][j-1] + grid[i-1][j-1]. Ardından (r1,c1) ile (r2,c2) arasındaki herhangi bir dikdörtgen toplamı sorgusu, dört erişim kullanılarak O(1) zamanda yanıtlanabilir.
def build_2d_prefix(grid):
R, C = len(grid), len(grid[0])
P = [[0]*(C+1) for _ in range(R+1)]
for r in range(1, R+1):
for c in range(1, C+1):
P[r][c] = (P[r-1][c] + P[r][c-1]
- P[r-1][c-1] + grid[r-1][c-1])
return P
def rect_sum(P, r1, c1, r2, c2):
return P[r2+1][c2+1] - P[r1][c2+1] - P[r2+1][c1] + P[r1][c1]
grid = [[3,0,1,4],[5,6,3,2],[1,2,0,1]]
P = build_2d_prefix(grid)
print(rect_sum(P, 0, 0, 1, 1)) # 3+0+5+6 = 14Denge Dizini için Kümülatif Toplam
Denge dizini, solundaki öğelerin toplamının sağındaki öğelerin toplamına eşit olduğu konumdur. Önce toplamı hesaplayın, ardından soldan tararken kümülatif sol toplamı tutun. Sağ toplam total - left_sum - nums[i] değeridir. Her dizinde eşitliği O(1) zamanda denetleyerek genel olarak O(n) zamana ulaşırsınız. Bu, kümülatif toplamın iki ayrı önek toplamı dizisinin yerini nasıl alabildiğini gösterir.
def find_pivot_index(nums):
total = sum(nums)
left_sum = 0
for i, n in enumerate(nums):
# right_sum = total - left_sum - nums[i]
if left_sum == total - left_sum - n:
return i
left_sum += n
return -1
print(find_pivot_index([1, 7, 3, 6, 5, 6])) # 3
print(find_pivot_index([1, 2, 3])) # -1Kendisi Hariç Çarpımlar Dizisi
Bir dizi verildiğinde, her öğesi diğer tüm öğelerin çarpımı olan bir dizi döndürün. Bölme işlemine izin verilmez. önek çarpımı ve sonek çarpımı kullanın: result[i] = (i'den önceki tüm öğelerin çarpımı) × (i'den sonraki tüm öğelerin çarpımı). Önek çarpımlarını soldan sağa bir geçişte oluşturun, ardından bir kümülatif değişken kullanarak sağdan sola bir geçişte sonek çarpımlarıyla çarpın — sonek için ek bir dizi gerekmez.
def product_except_self(nums):
n = len(nums)
result = [1] * n
# Left pass: result[i] = product of nums[:i]
prefix = 1
for i in range(n):
result[i] = prefix
prefix *= nums[i]
# Right pass: multiply in product of nums[i+1:]
suffix = 1
for i in range(n-1, -1, -1):
result[i] *= suffix
suffix *= nums[i]
return result
print(product_except_self([1, 2, 3, 4]))
# [24, 12, 8, 6] O(n) time, O(1) extra spaceMod ile Önek Toplamı
Bazı problemler, toplamı k'ye bölünebilen alt dizilerin sayısını sorar. Önek toplamlarını k modülüne göre kullanarak şu sonuca ulaşırız: prefix[j] % k == prefix[i] % k ise sum(i+1..j) k'ye bölünebilir. Tarama sırasında her kalan değerini sayan bir karma harita O(n) zaman sağlar. Başlangıçta yapılması gereken temel tanımlama, 0 dizininden başlayan alt dizileri ele almak için freq[0] = 1 ifadesidir.
from collections import defaultdict
def subarray_div_by_k(nums, k):
freq = defaultdict(int)
freq[0] = 1
current = 0
count = 0
for n in nums:
current = (current + n) % k
count += freq[current]
freq[current] += 1
return count
print(subarray_div_by_k([4, 5, 0, -2, -3, 1], 5))
# 7 (seven subarrays divisible by 5)Aralık Güncellemeleri için Fark Dizisi
Bir fark dizisi, önek toplamının tersidir. Bir dizi verildiğinde diff[i] = nums[i] - nums[i-1] değerini önceden hesaplayın. [l, r] aralığına x eklemek, fark dizisi üzerinde yalnızca iki O(1) işlemi gerektirir: diff[l] += x ve diff[r+1] -= x. Tüm güncellemelerden sonra, tek bir önek toplamı geçişiyle sonuç dizisini yeniden oluşturun. Böylece k aralık güncellemesinin maliyeti O(n×k) yerine O(n + k) olur.
def apply_range_updates(n, updates):
# updates: list of (l, r, val)
diff = [0] * (n + 1)
for l, r, val in updates:
diff[l] += val
diff[r+1] -= val
# Reconstruct with prefix sum
result = []
running = 0
for i in range(n):
running += diff[i]
result.append(running)
return result
# Add 3 to [1,3], add 1 to [0,2]
print(apply_range_updates(5, [(1,3,3),(0,2,1)]))
# [1, 4, 4, 3, 0]Mülakat Problemlerinde Önek Toplamı
Önek toplamları birçok problem kategorisinde karşımıza çıkar:
- Aralık sorguları — alt dizi toplamı, dikdörtgen toplamı
- Alt dizi sayımı — toplamın k'ye eşit olması, k'ye bölünebilir olması
- Çarpım problemleri — kendisi hariç çarpım
- Denge — pivot dizinini bulma
- Aralık güncellemeleri — fark dizisi
# Template: prefix sum + hash map for subarray problems
from collections import defaultdict
def subarray_count_template(nums, target):
"""
Count subarrays with property involving prefix sums.
Adapt 'target' and lookup condition for each problem.
"""
freq = defaultdict(int)
freq[0] = 1 # empty prefix at sum=0
current = 0
count = 0
for n in nums:
current += n
count += freq[current - target] # adjust per problem
freq[current] += 1
return count
print(subarray_count_template([1,2,3,2,1], 3)) # 3Kümülatif Toplam ve Kümülatif Maksimum
Önek toplamlarının yanı sıra birçok problem, tek bir değişkenle tutulan bir kümülatif maksimum veya kümülatif minimum kullanır. Hisse senedi alıp satmak için en iyi zaman probleminde kümülatif bir minimum fiyat; soldan yağmur suyu biriktirme probleminde ise kümülatif bir sol yükseklik maksimumu kullanılır. Bu desenler yalnızca bir tarama ve O(1) ek bellek gerektirir; bu da onları hem zaman hem de bellek verimliliği açısından altın standart hâline getirir.
def max_profit(prices):
# Running minimum buy price
min_price = float('inf')
max_prof = 0
for price in prices:
if price < min_price:
min_price = price
elif price - min_price > max_prof:
max_prof = price - min_price
return max_prof
def left_max_array(heights):
# Running max from left for trapping rain water
n = len(heights)
left_max = [0] * n
left_max[0] = heights[0]
for i in range(1, n):
left_max[i] = max(left_max[i-1], heights[i])
return left_max
print(max_profit([7,1,5,3,6,4])) # 5Hızlı Kontrol
Bu dersteki Veri Yapıları & Algoritmalar — Kodlama Mülakatı Hazırlığı kavramlarını ne ölçüde anladığınızı sınayın.
Ders Özeti
Bu derste şunları öğrendiniz: önek toplamları, kümülatif toplamları tek bir O(n) geçişte önceden hesaplayarak O(n) aralık sorgularını O(1) erişimlere dönüştürür, önek toplamlarını bir karma haritayla birleştirmek, belirli bir toplama veya bölünebilirlik özelliğine sahip alt dizileri saymak için O(n) zamanlı çözümler sağlar ve fark dizileri bunun tersidir: sonunda tek bir önek toplamı yeniden oluşturma geçişiyle O(1) aralık güncellemelerine olanak tanırlar. Sırada, zıt uçlardaki işaretçilerle başlayarak iki işaretçi tekniğini ele alacağız.
Sıkça Sorulan Sorular
“Ön Ek Toplamları ve Birikimli Toplamlar” dersi ücretsiz mi?
Evet — “Ön Ek Toplamları ve Birikimli Toplamlar” dersin tüm metni burada web'de ücretsiz olarak okunabilir. Etkileşimli olarak pratik yapmak (yerleşik kod editörü ve 7/24 yapay zeka koçu) ve DSA Interview Prep kursunun geri kalanını açmak için CoddyKit PRO'ya yükselt. DSA Interview Prep kursu toplamda 4 dersten oluşur.
“Ön Ek Toplamları ve Birikimli Toplamlar” dersinde ne öğreneceğim?
O(1) sürede aralık toplamı sorgularını yanıtlamak için ön ek toplam dizileri oluşturun ve bu tekniği maksimum toplamlı alt dizi gibi alt dizi problemlerine uygulayın. DSA Interview Prep ile uygulamalı kodu tarayıcıda doğrudan çalıştırarak pratik yaparsın ve 7/24 yapay zeka koçu dersi çalışırken sorularını yanıtlar.
DSA Interview Prep öğrenmeye başlamak için deneyim gerekli mi?
Önceden deneyim gerekmez. CoddyKit'te DSA Interview Prep, başlangıçtan ileri seviyeye kadar yapılandırıldığı için buradan başlayabilir veya başından başlayıp kendi hızında ilerleme yapabilirsin. Bu, 4 dersinin 2. dersidir.
“Ön Ek Toplamları ve Birikimli Toplamlar” dersi ne kadar sürer?
Çoğu CoddyKit dersi yaklaşık 5–10 dakika sürer. Her biri kısa ve etkileşimli olduğu için sabit ilerleme yaparsın ve web ile uygulama arasında tam olarak bıraktığın yerden devam edebilirsin.
Bu DSA Interview Prep dersinde kod yazıp çalıştırabilir miyim?
Evet. Her DSA Interview Prep dersi yerleşik bir kod editörü içerir, bu sayede tarayıcıda gerçek kod yazıp çalıştırabilir ve anlık yapay zeka geri bildirimi alırsın — yerel kurulum gerekli değildir.
Bu kursun tüm dersleri
- Dizi Temelleri ve Yerinde İşlemler
- Ön Ek Toplamları ve Birikimli Toplamlar
- İki İşaretçi: Karşıt Uçlar
- İki İşaretçi: Yavaş ve Hızlı