0Pricing
Coding Interview Prep · Ders

Big-O Gösterimine Sıfırdan Başlama

Asimptotik büyümeyi neden önemsediğimizi, sabitleri ve düşük dereceli terimleri nasıl göz ardı edeceğinizi ve Big-O gösterimini bir bakışta nasıl okuyacağınızı anlayın.

Big-O Gösterimine Sıfırdan Başlama, CoddyKit'te ücretsiz bir Coding Interview Prep dersidir. Bu, 4 dersinin 1. 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.

Algoritma Verimliliği Neden Ölçülür

İki program da doğru olabilir; ancak biri göz açıp kapayıncaya kadar tamamlanırken diğeri saatlerce çalışabilir. Zaman karmaşıklığı, girdi büyüdükçe çalışma süresinin nasıl arttığını açıklar.

# O(n) approach
def find_max_linear(nums):
    m = nums[0]
    for n in nums:
        if n > m: m = n
    return m

# O(n^2) approach (unnecessary double loop)
def find_max_quadratic(nums):
    for i in range(len(nums)):
        is_max = all(nums[i] >= nums[j] for j in range(len(nums)))
        if is_max: return nums[i]

print(find_max_linear([3, 1, 4, 1, 5, 9]))  # 9

Big-O: Asimptotik Üst Sınır

Big-O, maliyetin ne kadar hızlı büyüdüğüne ilişkin en kötü durum üst sınırını açıklar. Yöntem şudur: Sabitleri ve daha küçük terimleri atın; çünkü büyük ölçekte yalnızca baskın terim önemlidir. Koda bakın.

# T(n) = 3n^2 + 5n + 100 is O(n^2)
# because the n^2 term dominates for large n

# T(n) = 2n + 1000 is O(n)
# the constant 1000 becomes negligible

# Rule: drop constants and lower-order terms
# 5n^3 + 2n^2 + n + 1  =>  O(n^3)
# 100 * log(n) + n      =>  O(n)
print('O(n^2) example: counting iterations')
n = 1000
count = sum(1 for i in range(n) for j in range(n))
print(count)  # 1_000_000 = n^2

Yaygın Karmaşıklık Sınıfları

En hızlıdan en yavaşa: O(1), O(log n), O(n), O(n log n), O(n^2), O(2^n), O(n!). Bunları bilmek, tek bir satır yazmadan önce doğru yaklaşımı seçmenizi sağlar.

import math

n = 1000
print(f'O(1):       {1}')
print(f'O(log n):   {int(math.log2(n))}')
print(f'O(n):       {n}')
print(f'O(n log n): {int(n * math.log2(n))}')
print(f'O(n^2):     {n**2}')
# O(2^n) for n=1000 is astronomically large
# O(n!) even larger

Sabitleri Atmak: Neden Önemlidir

5n adım çalıştırmak da 2n adım çalıştırmak da O(n) değerindedir; sabitler algoritmaya değil, donanıma bağlıdır. Büyük O, aynı koşullarda ölçeklenmeyi karşılaştırabilmeniz için bu sabitleri göz ardı eder.

# Both are O(n) — different constants
def count_a(n):
    total = 0
    for i in range(n):   # n ops
        total += 1
    for i in range(n):   # n ops
        total += 1
    return total  # T(n) = 2n  =>  O(n)

def count_b(n):
    total = 0
    for i in range(5 * n):  # 5n ops
        total += 1
    return total  # T(n) = 5n  =>  O(n)

print(count_a(10), count_b(10))  # 20 50

En İyi, Ortalama ve En Kötü Durumlar

Büyük O en kötü durumu ifade eder; Omega en iyi durumu, Theta ise her ikisi için sıkı bir sınırı ifade eder. Bir mülakatçı "karmaşıklık" dediğinde neredeyse her zaman en kötü durumu kasteder.

def linear_search(nums, target):
    for i, n in enumerate(nums):
        if n == target:
            return i  # best case: target at index 0 => O(1)
    return -1         # worst case: not found => O(n)

# Best case O(1): target is first element
print(linear_search([5,1,2,3], 5))   # 0

# Worst case O(n): target not in list
print(linear_search([1,2,3,4], 9))   # -1

O(log n): Arama Alanını Yarıya İndirmek

Bir algoritma her adımda girdiyi yarıya indiriyorsa, ikili aramada olduğu gibi, O(log n) değerindedir. Bir milyar öğe için bile bu yalnızca yaklaşık 30 adımdır; inanılmaz derecede hızlıdır. Kodu inceleyin.

def binary_search(arr, target):
    lo, hi = 0, len(arr) - 1
    steps = 0
    while lo <= hi:
        steps += 1
        mid = (lo + hi) // 2
        if arr[mid] == target:
            return mid, steps
        elif arr[mid] < target:
            lo = mid + 1
        else:
            hi = mid - 1
    return -1, steps

import math
arr = list(range(1000))
idx, s = binary_search(arr, 999)
print(f'Found at {idx} in {s} steps (log2(1000)~={math.log2(1000):.1f})')

O(n log n): Sıralamanın Alt Sınırı

Karşılaştırmalı her sıralama algoritması, en kötü durumda en az O(n log n) adım gerektirir; bu gerçek bir matematiksel alt sınırdır. Bu nedenle önce sıralayıp sonra taramak genel olarak O(n log n) değerindedir, O(n^2) değil. Kodda birleştirmeli sıralama gösteriliyor.

# Merge sort: O(n log n)
def merge_sort(arr):
    if len(arr) <= 1:
        return arr
    mid = len(arr) // 2
    left  = merge_sort(arr[:mid])
    right = merge_sort(arr[mid:])
    return merge(left, right)

def merge(a, b):
    res, i, j = [], 0, 0
    while i < len(a) and j < len(b):
        if a[i] <= b[j]: res.append(a[i]); i+=1
        else:             res.append(b[j]); j+=1
    return res + a[i:] + b[j:]

print(merge_sort([5,2,8,1,9,3]))  # [1,2,3,5,8,9]

Amortismanlı Karmaşıklık

Amortismanlı analiz, maliyeti çok sayıda işlem üzerine yayarak ortalamasını alır. Python'daki append amortismanlı olarak O(1) değerindedir: çoğu zaman anında gerçekleşir; nadir görülen O(n) boyutlandırma maliyeti tüm append işlemlerine küçük paylar hâlinde dağıtılır.

# Dynamic array append is O(1) amortised
import sys

lst = []
capacities = []
for i in range(16):
    lst.append(i)
    capacities.append(sys.getsizeof(lst))

# Size jumps show reallocation events
for i, c in enumerate(capacities):
    if i > 0 and capacities[i] != capacities[i-1]:
        print(f'Realloc at i={i}, new size={c} bytes')

Kodda Karmaşıklığı Tanımak

Hızlı bir kural: döngüleri sayın. Tek döngü O(n), iç içe iki döngü O(n^2), yarıya inen bir döngü O(log n) değerindedir. Bağımsız geçişler add; yalnızca iç içe döngüler çarpar. Kodu inceleyin.

# Two independent passes: O(n) + O(n) = O(n)
def two_passes(nums):
    total = sum(nums)           # O(n)
    mean = total / len(nums)
    diffs = [abs(n - mean) for n in nums]  # O(n)
    return max(diffs)           # O(n)
# Overall: O(n) -- NOT O(n^2)

# Nested loops: O(n) * O(n) = O(n^2)
def all_pairs(nums):
    pairs = []
    for i in range(len(nums)):       # O(n)
        for j in range(i+1, len(nums)): # O(n)
            pairs.append((nums[i], nums[j]))
    return pairs  # O(n^2)

Uzay Karmaşıklığının Temelleri

Uzay karmaşıklığı, girdi dışında kullandığınız ek belleği izler. Yerinde ters çevirme O(1), bir karma tablosu ise O(n) değerindedir. Zamanı alanla değiş tokuş ettiğinizde her zaman ikisini de belirtin.

# O(1) space: reverse in-place
def reverse_inplace(arr):
    l, r = 0, len(arr) - 1
    while l < r:
        arr[l], arr[r] = arr[r], arr[l]
        l += 1; r -= 1

# O(n) space: create reversed copy
def reverse_copy(arr):
    return arr[::-1]

a = [1, 2, 3, 4, 5]
reverse_inplace(a)
print(a)  # [5, 4, 3, 2, 1]

Mülakatlarda Karmaşıklıktan Söz Etmek

Sorulmasını beklemeden her zaman karmaşıklığı kendiniz belirtin: "Bu işlem O(n log n) zaman ve O(n) alan kullanır." Ardından daha hızlı bir seçenek sunun. Bu alışkanlık gerçek bir kıdem göstergesidir.

# Example of explaining complexity step by step
def two_sum(nums, target):
    # O(n) time: one pass through nums
    # O(n) space: hash map stores up to n elements
    seen = {}  # value -> index
    for i, n in enumerate(nums):
        complement = target - n
        if complement in seen:   # O(1) lookup
            return [seen[complement], i]
        seen[n] = i
    return []

print(two_sum([2, 7, 11, 15], 9))  # [0, 1]

Hızlı Kontrol

Hızlı kontrol — Büyük O ve karmaşıklık sınıfları hakkında öğrendiklerinizi gösterin. Tek bir soru var; bunu yapabilirsiniz. 🎯

Ders Özeti

Özet: Büyük O, sabitlerin göz ardı edildiği en kötü durum büyümesini ifade eder; O(1)'den O(n!)'e kadar olan sınıfları biliyorsunuz ve bağımsız döngüler toplanırken iç içe döngüler çarpılır.

Sıkça Sorulan Sorular

“Big-O Gösterimine Sıfırdan Başlama” dersi ücretsiz mi?

Evet — “Big-O Gösterimine Sıfırdan Başlama” 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.

“Big-O Gösterimine Sıfırdan Başlama” dersinde ne öğreneceğim?

Asimptotik büyümeyi neden önemsediğimizi, sabitleri ve düşük dereceli terimleri nasıl göz ardı edeceğinizi ve Big-O gösterimini bir bakışta nasıl okuyacağınızı anlayı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 1. dersidir.

“Big-O Gösterimine Sıfırdan Başlama” 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. Big-O Gösterimine Sıfırdan Başlama
  2. Döngüleri ve İç İçe Döngüleri İnceleme
  3. Özyineleme ve Özyineleme Ağacı Yöntemi
  4. Alan Karmaşıklığı ve Ödünleşimler
← Coding Interview Prep Sayfasına Dön