0Pricing
Coding Interview Prep · Ders

Ö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 Coding 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, Coding Interview Prep öğrenme yolunun bir parçasıdır ve ilerlemeniz web ve CoddyKit uygulaması arasında senkronize olur. Coding 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))  # 15

Alt 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]))
# -1

Izgara 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 = 14

Denge 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]))             # -1

Kendisi 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 space

Mod 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
Kümülatif toplamlar veya aralık tabanlı birleştirmeler içeren bir problem gördüğünüzde önce önek toplamını düşünün. Bu, neredeyse her zaman naif O(n²) kaba kuvvet çözümünden O(n) zamanlı bir çözüm elde etmenizi sağlar.

# 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))  # 3

Kü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]))  # 5

Hı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 Coding Interview Prep kursunun geri kalanını açmak için CoddyKit PRO'ya yükselt. Coding 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. Coding 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.

Coding Interview Prep öğrenmeye başlamak için deneyim gerekli mi?

Önceden deneyim gerekmez. CoddyKit'te Coding 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 Coding Interview Prep dersinde kod yazıp çalıştırabilir miyim?

Evet. Her Coding 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

  1. Dizi Temelleri ve Yerinde İşlemler
  2. Ön Ek Toplamları ve Birikimli Toplamlar
  3. İki İşaretçi: Karşıt Uçlar
  4. İki İşaretçi: Yavaş ve Hızlı
← Coding Interview Prep Sayfasına Dön