0Pricing
Coding Interview Prep · Ders

Anagramlar ve Karakter Sıklığı Haritaları

O(n) çözümler üretmek için sıklık dizilerini ve karma tablolarını kullanarak anagramları gruplama, geçerli anagram ve dizede permütasyon problemlerini çözün.

Anagramlar ve Karakter Sıklığı Haritaları, CoddyKit'te ücretsiz bir Coding Interview Prep dersidir. Bu, 4 dersinin 3. 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.

Anagram Nedir

İki dize, aynı karakterleri aynı sıklıklarda ancak farklı sırada içeriyorsa anagramdır. 'listen' ve 'silent' anagramdır. En basit doğruluk denetimi, her iki dizeyi sıralayıp karşılaştırmaktır: O(n log n). O(n) çözümler için karakter frekans haritalarını karşılaştırın. Anagram problemleri, karma işlemi, sıralama ve frekans dizileri gibi birden fazla tekniği sınadıkları için dize mülakatlarının temel konularındandır.

def is_anagram_sort(s, t):
    return sorted(s) == sorted(t)  # O(n log n)

def is_anagram_counter(s, t):
    from collections import Counter
    return Counter(s) == Counter(t)  # O(n)

def is_anagram_array(s, t):
    if len(s) != len(t): return False
    freq = [0] * 26
    for a, b in zip(s, t):
        freq[ord(a) - ord('a')] += 1
        freq[ord(b) - ord('a')] -= 1
    return all(f == 0 for f in freq)  # O(n)

print(is_anagram_array('anagram', 'nagaram'))  # True
print(is_anagram_array('rat', 'car'))           # False

Küçük Harfler için Frekans Dizisi

Karakter kümesi sınırlı olduğunda (örneğin yalnızca küçük harfli a-z), karma haritası yerine boyutu 26 olan bir frekans dizisi kullanın. ord(c) - ord('a') ile dizinleme, 'a'→0, 'b'→1, ..., 'z'→25 eşlemesini yapar. Önbellek yerelliği ve karma işlemi ek yükünün bulunmaması sayesinde diziler pratikte sözlüklerden daha hızlıdır. Bu teknik geçerli anagram, dizede anagram permütasyonu ve palindrom permütasyonu problemlerinde karşımıza çıkar.

def build_freq(s):
    freq = [0] * 26
    for c in s:
        freq[ord(c) - ord('a')] += 1
    return freq

def is_anagram_fast(s, t):
    return len(s) == len(t) and build_freq(s) == build_freq(t)

# Palindrome permutation: at most one odd-count character
def can_form_palindrome(s):
    freq = build_freq(s)
    odd_count = sum(1 for f in freq if f % 2 == 1)
    return odd_count <= 1

print(can_form_palindrome('carerace'))  # True ('racecar')
print(can_form_palindrome('hello'))     # False

Anagramları Gruplama

Bir dize listesini, tüm anagramlar bir arada görünecek şekilde gruplayın. Standart O(n×m log m) çözümünde, sıralanmış dize karma haritası anahtarı olarak kullanılır. Tüm anagramlar aynı sıralanmış anahtarı oluşturduğundan aynı kovaya yerleşir. O(n×m) olan bir başka yöntemde anahtar olarak karakter sayılarından oluşan bir demet kullanılır; bu yöntemin hesaplanması daha yavaştır ancak sıralama gerektirmez. Sıralanmış anahtar yaklaşımı, açıklığa önem verildiğinde neredeyse her zaman tercih edilir.

from collections import defaultdict

def group_anagrams(strs):
    groups = defaultdict(list)
    for s in strs:
        key = tuple(sorted(s))  # or ''.join(sorted(s))
        groups[key].append(s)
    return list(groups.values())

words = ['eat','tea','tan','ate','nat','bat']
result = group_anagrams(words)
for g in sorted(result, key=len, reverse=True):
    print(sorted(g))
# ['ate', 'eat', 'tea']
# ['nat', 'tan']
# ['bat']

Sayı Demetiyle Anagram Anahtarı

O(n×m) anagram gruplama çeşidinde, her dizenin frekansını 26 sayıdan oluşan bir demet olarak gösterin: tuple(freq_array). Bu, sıralamayı önler ancak tüm anahtarları oluşturmak için O(26×n×m) işlem gerektirir. Demetler Python'da karma değerine dönüştürülebildiğinden geçerli sözlük anahtarlarıdır. Mülakatçı 'herhangi bir O(n×m) çözümü' istediğinde bu çeşitten söz etmek yararlıdır; farklı ödünleşimleri anladığınızı gösterir.

from collections import defaultdict

def group_anagrams_count(strs):
    groups = defaultdict(list)
    for s in strs:
        freq = [0] * 26
        for c in s:
            freq[ord(c) - ord('a')] += 1
        key = tuple(freq)  # tuple is hashable
        groups[key].append(s)
    return list(groups.values())

print(group_anagrams_count(['eat','tea','tan','ate','nat','bat']))

En Sık Görülen K Öğesi

Bir dizide en sık görülen k öğeyi bulun. Sayaç + yığın: O(n) içinde bir frekans haritası oluşturun, ardından k boyutlu bir min-yığın veya Counter.most_common(k) kullanarak en yüksek k frekansı çıkarın. O(n) zamanlı kova sıralaması yaklaşımında frekansa göre (0'dan n'e kadar) dizinlenen kovalar oluşturulur ve öğeler frekansları azalan sırada toplanır; k büyük olduğunda bu yaklaşım zariftir.

from collections import Counter
import heapq

def top_k_frequent_heap(nums, k):
    freq = Counter(nums)
    return heapq.nlargest(k, freq, key=freq.get)

def top_k_frequent_bucket(nums, k):
    freq = Counter(nums)
    buckets = [[] for _ in range(len(nums) + 1)]
    for num, cnt in freq.items():
        buckets[cnt].append(num)
    result = []
    for i in range(len(buckets)-1, -1, -1):
        result.extend(buckets[i])
        if len(result) >= k: break
    return result[:k]

print(top_k_frequent_heap([1,1,1,2,2,3], 2))   # [1, 2]
print(top_k_frequent_bucket([1,1,1,2,2,3], 2)) # [1, 2]

Dizede Permütasyon için Frekans Haritası

p dizesinin herhangi bir permütasyonunun s içinde alt dize olarak bulunup bulunmadığını belirleyin. |p| uzunluğundaki bir pencerenin frekans haritası, p'nin frekans haritasına eşit olmalıdır. Pencere kayarken giren karakterin sayısını artırın ve çıkan karakterin sayısını azaltın. İki sayaç nesnesini karşılaştırmak her seferinde O(26) sürer; böylece toplam süre O(n×26) = O(n) olur. O(1) zamanlı eşitlik denetimi için karşılanma sayacını izleyin.

def check_inclusion_fast(p, s):
    if len(p) > len(s): return False
    need = [0] * 26
    have = [0] * 26
    for c in p:
        need[ord(c)-ord('a')] += 1
    for i in range(len(p)):
        have[ord(s[i])-ord('a')] += 1
    if need == have: return True
    for i in range(len(p), len(s)):
        have[ord(s[i])-ord('a')]         += 1
        have[ord(s[i-len(p)])-ord('a')] -= 1
        if need == have: return True
    return False

print(check_inclusion_fast('ab', 'eidbaooo'))  # True
print(check_inclusion_fast('ab', 'eidboaoo'))  # False

Anagram Oluşturmak için Minimum Karakter Sayısı

İki dize verildiğinde, birinin diğerinin anagramı olması için gereken minimum karakter silme sayısını bulun. Her iki dize için frekans haritaları oluşturun; yanıt, frekansların mutlak farklarının toplamıdır. Birinde bulunup diğerinde bulunmayan karakterlerin tamamı silinmelidir. Bu O(n) çözümü, frekans haritalarında 'birleştir ve fark al' kalıbını kullanır.

from collections import Counter

def min_steps_to_anagram(s, t):
    freq_s = Counter(s)
    freq_t = Counter(t)
    steps = 0
    # For each unique char across both strings:
    all_chars = set(freq_s) | set(freq_t)
    for c in all_chars:
        steps += abs(freq_s.get(c, 0) - freq_t.get(c, 0))
    return steps

# Or more concisely:
def min_steps_counter(s, t):
    diff = Counter(s) - Counter(t)
    return sum(diff.values())

print(min_steps_to_anagram('leetcode', 'practice'))  # 5
print(min_steps_counter('leetcode', 'practice'))      # 5

Fidye Notu için Frekans Haritası

note içindeki tüm karakterlerin magazine içindeki karakterlerle karşılanıp karşılanamayacağını denetleyin (dergideki her karakter yalnızca bir kez kullanılabilir). Dergi karakterlerinin frekans haritasını oluşturun; ardından nottaki her karakter için sayıyı azaltın. Herhangi bir sayı negatife düşerse Yanlış döndürün. Bu işlem O(n + m) zaman alır; küçük harflerle sınırlı girdilerde sözlük yerine 26 elemanlı bir dizi kullanılırsa alan O(1)'dir.

def can_construct(note, magazine):
    freq = [0] * 26
    for c in magazine:
        freq[ord(c) - ord('a')] += 1
    for c in note:
        freq[ord(c) - ord('a')] -= 1
        if freq[ord(c) - ord('a')] < 0:
            return False  # insufficient supply
    return True

print(can_construct('aa', 'aab'))    # True
print(can_construct('aa', 'ab'))     # False
print(can_construct('bg', 'efjbdfbdgbjjbghiklgdch'))  # True

En Uzun Anagram Alt Dizesi için Karma

Aynı dizedeki iki alt dizenin anagram olup olmadığını denetlemek için, değişme özelliğine sahip (sıradan bağımsız) bir polinom karakter karması kullanın. Karakter değerlerinin XOR işlemi değişme özelliğine sahiptir ve O(1) içinde güncellenebilir; ancak çakışma olasılığı yüksektir. Daha iyi bir yaklaşımda asal çarpım karması kullanılır (her karakter farklı bir asala eşlenir ve çarpım sıradan bağımsız olur). Bu, ileri düzey mülakatlara özgü bir tekniktir.

# Prime product hash: each char maps to a prime
PRIMES = [2,3,5,7,11,13,17,19,23,29,31,37,41,
          43,47,53,59,61,67,71,73,79,83,89,97,101]

def char_hash(s):
    h = 1
    for c in s:
        h *= PRIMES[ord(c) - ord('a')]
    return h

# Two windows with equal hash are likely anagrams
print(char_hash('listen'))  # same as:
print(char_hash('silent'))  # should match

Frekans Haritası Kalıpları Denetim Listesi

Şu frekans haritası mülakat kalıplarını tanıyın:

  • Geçerli anagram: aynı uzunluk + aynı frekans → sayaç eşitliği veya dizi karşılaştırması
  • Anagramları gruplama: sözlük anahtarı olarak sıralanmış dize veya frekans demeti
  • En sık görülen k öğe: sayaç + yığın veya kova sıralaması
  • Dizede permütasyon: kayan pencere + frekans karşılaştırması
  • Fidye notu: kaynak frekans haritası, talep için azaltma
  • Palindrom permütasyonu: en fazla bir tek sayıda görünen karakter
Bunların her biri aynı temel fikre indirgenir: parmak izi olarak frekans.

from collections import Counter

# Palindrome permutation
def palindrome_permutation(s):
    return sum(v % 2 for v in Counter(s).values()) <= 1

# First unique character
def first_unique(s):
    freq = Counter(s)
    for i, c in enumerate(s):
        if freq[c] == 1:
            return i
    return -1

# Character replacement for longest repeat
def char_replacement(s, k):
    freq = Counter()
    left = best = max_freq = 0
    for right, c in enumerate(s):
        freq[c] += 1
        max_freq = max(max_freq, freq[c])
        if (right - left + 1) - max_freq > k:
            freq[s[left]] -= 1
            left += 1
        best = max(best, right - left + 1)
    return best

print(palindrome_permutation('carerace'))  # True
print(first_unique('leetcode'))             # 0
print(char_replacement('AABABBA', 1))      # 4

Tek Farklı: Frekans için XOR

Tam olarak bir öğe tek sayıda göründüğünde XOR, frekans problemleri için güçlü bir araçtır. Bir sayının kendisiyle XOR işlemi sonucu 0 olur: a XOR a = 0. Bir değer dışındaki tüm değerler çift sayıda görünüyorsa, tüm öğelerin XOR işlemi yalnızca tek kalan öğeyi bırakır. Böylece karma haritasına gerek kalmadan O(n) zaman ve O(1) alan elde edilir. XOR özellikleri kullanılarak tek sayıda görünen iki sayıyı bulmaya da genellenebilir.

def single_number(nums):
    result = 0
    for n in nums:
        result ^= n  # XOR cancels pairs
    return result

print(single_number([4,1,2,1,2]))   # 4
print(single_number([2,2,1]))       # 1

# Find the unique character in an anagram check:
def find_difference(s, t):
    result = 0
    for c in s + t:
        result ^= ord(c)
    return chr(result)

print(find_difference('abcd', 'abcde'))  # 'e'

Hızlı Kontrol

Bu dersteki Veri Yapıları ve Algoritmalar — Kodlama Mülakatı Hazırlığı kavramlarını anlayıp anlamadığınızı sınayın.

Ders Özeti

Bu derste şunları öğrendiniz: karakter frekans haritaları, anagramları saptamak için temel araçtır — sınırlı alfabeler için 26 elemanlı bir dizi veya rastgele karakterler için bir sayaç kullanılabilir, sıralanmış dize ya da frekans demeti sözlük anahtarları, tüm anagramları sırasıyla O(n × m log m) veya O(n × m) zamanda bir araya getirir ve XOR, tek öğenin tek sayıda göründüğü problemlerde çiftleri düzgünce ortadan kaldırır; sözlük gerekmediğinde O(1) alanla O(n) zaman sağlar. Sırada dize kodlama, ters çevirme ve palindrom tekniklerini inceleyeceğiz.

Sıkça Sorulan Sorular

“Anagramlar ve Karakter Sıklığı Haritaları” dersi ücretsiz mi?

Evet — “Anagramlar ve Karakter Sıklığı Haritaları” 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.

“Anagramlar ve Karakter Sıklığı Haritaları” dersinde ne öğreneceğim?

O(n) çözümler üretmek için sıklık dizilerini ve karma tablolarını kullanarak anagramları gruplama, geçerli anagram ve dizede permütasyon problemlerini çözü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 3. dersidir.

“Anagramlar ve Karakter Sıklığı Haritaları” 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. Mülakatlar için Python Dize API’si
  2. Alt Dizeler için Kayan Pencere
  3. Anagramlar ve Karakter Sıklığı Haritaları
  4. Dize Kodlama, Ters Çevirme ve Palindromlar
← Coding Interview Prep Sayfasına Dön