Valid Anagram
İki dizgeden biri diğerinin yeniden düzenlenmiş hâliyse anagramdır: aynı harfleri, her harften de aynı sayıda kullanırlar. Küçük İngilizce harflerden oluşan iki s ve t dizgesi veriliyor. t, s'nin anagramıysa true, değilse false döndürün.
Fonksiyon
- sstring
- ilk dize, küçük harfler
- tstring
- s'ye karşı sınanacak dize
- Döndürürboolean
- t, s'deki harflerin her birini aynı sayıda kullanıyorsa true
Kısıtlar
1 ≤ s.length, t.length ≤ 2 × 104svetyalnızca küçük İngilizce harfler (ailezarası) içerir.- İki uzunluk farklı olabilir.
Örnekler
- Girdi
- s = "listen"t = "silent"
- Çıktı
- true
- Açıklama
- Her iki kelimede de birer
e,i,l,n,svetharfi bulunur; bu yüzdensilent, harflerinin yeri değiştirilmiş hâliylelistensözcüğüdür.
- Girdi
- s = "aabb"t = "abbb"
- Çıktı
- false
- Açıklama
- Uzunluklar eşleşiyor ve ikisi de yalnızca
avebkullanıyor, ancakaabbiçinde iki tanea,abbbiçinde ise bir tane var. Yalnızca harflerin değil, sayıların da eşleşmesi gerekir.
- Girdi
- s = "cat"t = "cast"
- Çıktı
- false
- Açıklama
castdört harflidir vecatüç harflidir, bu yüzdencatkelimesinin harflerini hiçbir şekilde yeniden düzenleyerek bunu yazamazsın.
Gönderirken +19 gizli test
Ek soru
Peki dizeler a'dan z'ye kadar olan karakterler yerine herhangi bir Unicode karakterini tutabilseydi? Sayımı nasıl değiştirirdin?
İpuçları
Tek tek açın. Her biri biraz daha fazlasını gösterir.
Anagram, harflerin sırasını dikkate almaz. Sırayı göz ardı edip her harfin kaç kez geçtiğini koruyan neyle karşılaştırabilirsiniz?
Harf harf sıralandıklarında, iki anagram aynı dizeye dönüşür. Daha da hızlısı: yalnızca 26 harf vardır, bu yüzden her birinin kaç kez geçtiğini sayabilirsiniz.
Uzunluklar farklıysa yanıt
falseolur. Aksi takdirde 26 sayaç tut:siçindeki her harf için 1 ekle vetiçindeki her harf için 1 çıkar. Dizeler, hiçbir sayaç sıfırın altına düşmediğinde tam olarak anagramdır.
Çözüm
Bir anagram harf sayılarını korur ve sıralamayı göz ardı eder. Bu yüzden harflerin nerede olduğunu unutan ama her birinden kaç tane olduğunu hatırlayan bir dize özeti gerekir. Sıralama bu özeti O(n log n) sürede oluşturur; 26 sayaçtan oluşan bir tablo ise tek geçişte oluşturur.
Her iki dizgeyi de sırala
Sezgi
Sıralama, bir dizgedeki harfleri alfabetik sıraya koyar ve her birinin başlangıçtaki konumunu siler. listen, eilnst olarak sıralanır; silent da aynı şekilde sıralandığından bunlar anagramdır. aabb, aabb olarak kalır ve abbb, abbb olarak kalır; 1. indekste farklı olduklarından anagram değildirler.
Test her iki yönde de çalışır. t, s'nin yeniden düzenlenmiş hâliyse ikisi de aynı harfleri aynı sayıda içerir, dolayısıyla sıralama aynı diziyi üretir. Sıralanmış diziler eşitse t, s'deki harflerin aynısını kullanır.
Önce uzunlukları karşılaştır: farklı uzunluktaki dizgeler asla anagram olmaz ve her iki sıralama işlemini de atlarsın. Sıralama O(n log n) zaman alır ve çoğu dil karakterlerin bir kopyasını sıralar; bu da O(n) ek alan gerektirir. n = 2 × 10^4 için bu hızlıdır, ancak sayma yaklaşımı daha az iş yapar.
Algoritma
svetuzunlukları farklıysafalsedöndür.- Her dizenin karakterlerini bir diziye kopyala.
- Her iki diziyi de sırala.
- Sıralanmış diziler eleman eleman eşitse
truedöndür.
def isAnagram(s, t):
if len(s) != len(t):
return False
return sorted(s) == sorted(t)Her harfi say
Sezgi
Yalnızca 26 harf görünebilir; bu yüzden 26 elemanlı bir dizide her harf için bir sayaç tutun: a için dizin 0, z için dizin 25 olsun. Bir harfin dizini, karakter kodundan a harfinin kodu çıkarılarak bulunur. s üzerinde ilerleyip her harfin sayacını 1 artırın, ardından t üzerinde ilerleyip 1 azaltın.
Erken durabilirsiniz: Bir sayacın 0'ın altına düşmesi, t içinde o harfin s içindekinden daha fazla kullanıldığı anlamına gelir. aabb ve abbb için s sonrasında sayaçlar a: 2 ve b: 2 değerini gösterir. Ardından t, b harfini üç kez alır; üçüncü seferde b -1 olur ve hemen false döndürürsünüz.
"Hiçbir sayaç negatif olmadı" demek neden yeterli? Dizelerin uzunlukları eşit olduğundan, her iki dolaşımın sonunda sayaçların toplamı 0 olur. Hiçbiri negatif değilse pozitif olan bir sayacı dengeleyecek bir değer olamaz; dolayısıyla tüm sayaçlar 0'dır ve harf sayıları eşleşir. Uzunluk kontrolünün yalnızca bir kısayol değil, gerekli olmasının nedeni budur.
Her dize bir kez okunur; bu da O(n) zaman demektir. Dizi, uzunluk ne olursa olsun her zaman 26 sayı tutar; dolayısıyla ek alan O(1)'dir.
Algoritma
svetdizelerinin uzunlukları farklıysafalsedöndür.- 26 sıfırdan oluşan bir dizi oluştur.
siçindeki her harf için sayacını 1 artır.tiçindeki her harf için sayacını 1 azalt; 0'ın altına düşersefalsedöndür.truedöndür.
def isAnagram(s, t):
if len(s) != len(t):
return False
counts = [0] * 26 # counts[0] is 'a', counts[25] is 'z'
for ch in s:
counts[ord(ch) - ord("a")] += 1
for ch in t:
index = ord(ch) - ord("a")
counts[index] -= 1
if counts[index] < 0:
return False # t uses this letter more often than s
return True
Tuzaklar ve uç durumlar
Yanlış yanıtların çoğu, harflerin kaç kez geçtiğine bakmak yerine hangi harflerin bulunduğunu kontrol etmekten veya uzunluk kontrolünü atlamaktan kaynaklanır.
- Harf kümelerini karşılaştırmak.
aabbveabbbtam olarak aynıavebharflerini kullanır, ancak anagram değildir. tiçindeki her harfin üzerini çizmedensiçinde bir yerde bulunduğunu kontrol etmek.aabveabbbu testi her iki yönde de geçer.- Sayma yönteminde uzunluk kontrolünü atlamak.
s = abvet = aolduğunda hiçbir sayaç 0'ın altına düşmez, dolayısıyla kod yanlışlıklatruedöndürür. - Sayaç dizisini ham karakter koduyla indekslemek.
a97'dir; bu, 26 elemanlı bir dizinin sınırını çok aşar. Öncea'nın kodunu çıkarın. Lua ve R'de, dizileri 1. indeksten başladığı için 1 ekleyin.
Sıkça sorulan sorular4
Geçerli Anagram'ın zaman karmaşıklığı nedir?
Harfleri saymak O(n) zaman ve O(1) ek alan alır; çünkü dizelerin uzunluğu ne olursa olsun sayaç dizisinde 26 öğe bulunur. Her iki diziyi sıralamak O(n log n) zaman ve sıralanmış kopyalar için genellikle O(n) alan alır.
Anagram kontrolü yaparken sıralamak mı yoksa saymak mı daha iyidir?
Sayma teorik olarak daha hızlıdır: O(n), O(n log n)'e kıyasla ve bir harf gereğinden fazla kullanıldığında hemen durabilir. Sıralama daha kısa yazılır ve herhangi bir alfabe için değişiklik gerektirmeden çalışır. Bir mülakatta önce sıralamadan bahset, ardından saymaya geçerek iyileştir.
Unicode karakterler içeren anagramları nasıl kontrol edersiniz?
26 sayaçtan oluşan diziyi, karakterden sayıya eşleme yapan bir hash map ile değiştirin. s içindeki her karakter için 1 ekleyin, t içindeki her karakter için 1 çıkarın ve her sayacın 0'da kaldığını kontrol edin. Dizeleri bayt bayt değil, karakterlerin tamamını okuyarak işleyin; böylece birkaç baytta saklanan bir karakter bir kez sayılır.
Neden iki tane yerine tek bir sayaç dizisi kullanılır?
Her bir dizge için bir dizi kullanmak da işe yarar: her dizgedeki karakterleri say, ardından dizileri karşılaştır. s için artan ve t için azalan tek bir dizi, belleğin yarısını kullanır ve bir sayaç negatif olur olmaz, son bir karşılaştırma döngüsüne gerek kalmadan false döndürmeni sağlar.
Benzer problemler
Aynı fikirleri kullanan problemler. İki üçünü çözmek bir kalıbı kalıcı hale getirir.
Python
def isAnagram(s, t):
# Kodu buraya yazınDurum 1
Durum 2
Durum 3
Girdi
s = "listen" t = "silent"
Beklenen
true