Valid Anagram
Dua string disebut anagram jika salah satunya merupakan susunan ulang dari yang lain: keduanya menggunakan huruf yang sama, dengan jumlah kemunculan yang sama untuk setiap huruf. Kamu mendapatkan dua string s dan t yang terdiri dari huruf kecil bahasa Inggris. Kembalikan true jika t adalah anagram dari s, dan false jika tidak.
Fungsi
- sstring
- string pertama, huruf kecil
- tstring
- string yang akan diuji terhadap s
- Mengembalikanboolean
- benar jika t menggunakan huruf-huruf s secara persis, masing-masing dengan jumlah yang sama
Batasan
1 ≤ s.length, t.length ≤ 2 × 104sdanthanya berisi huruf kecil bahasa Inggris (ahinggaz).- Panjang keduanya bisa berbeda.
Contoh
- Input
- s = "listen"t = "silent"
- Output
- true
- Penjelasan
- Kedua kata memiliki satu
e,i,l,n,s, dant, jadisilentadalahlistendengan huruf-hurufnya yang diacak.
- Input
- s = "aabb"t = "abbb"
- Output
- false
- Penjelasan
- Panjangnya sama dan keduanya hanya menggunakan
adanb, tetapiaabbmemiliki duaadanabbbmemiliki satu, jadi jumlahnya berbeda.
- Input
- s = "cat"t = "cast"
- Output
- false
- Penjelasan
castterdiri dari empat huruf dancatterdiri dari tiga huruf, jadi tidak ada penyusunan ulangcatyang dapat mengejanya.
Pertanyaan lanjutan
Bagaimana jika string dapat menyimpan karakter Unicode apa pun, bukan hanya a sampai z? Bagaimana kamu akan mengubah penghitungannya?
Petunjuk
Buka satu per satu. Setiap petunjuk mengungkap sedikit lebih banyak.
Anagram mengabaikan urutan huruf. Apa yang bisa kamu bandingkan yang mengabaikan urutan, tetapi tetap mempertahankan berapa kali setiap huruf muncul?
Jika diurutkan huruf demi huruf, dua anagram menjadi string yang sama. Cara yang lebih cepat: hanya ada 26 huruf, jadi kamu bisa menghitung berapa kali setiap huruf muncul.
Jika panjangnya berbeda, jawabannya adalah
false. Jika tidak, pertahankan 26 penghitung: tambahkan 1 untuk setiap huruf dalamsdan kurangi 1 untuk setiap huruf dalamt. Kedua string adalah anagram tepat ketika tidak ada penghitung yang pernah turun di bawah nol.
Solusi
Anagram mempertahankan jumlah setiap huruf dan mengabaikan urutannya. Jadi, kamu perlu ringkasan dari setiap string yang tidak mengingat posisi huruf, tetapi mengingat jumlah setiap huruf. Pengurutan membangun ringkasan itu dalam O(n log n); tabel berisi 26 penghitung membangunnya dalam satu kali lintasan.
Urutkan kedua string
Intuisi
Pengurutan menata huruf dalam string menurut urutan alfabet dan menghapus informasi tentang posisi awal setiap huruf. listen dan silent sama-sama menjadi eilnst setelah diurutkan; aabb dan abbb tetap seperti semula dan berbeda pada indeks 1. Dua string memiliki huruf yang sama dengan jumlah kemunculan yang sama persis jika bentuk terurutnya sama.
Bandingkan panjangnya terlebih dahulu dan lewati kedua pengurutan jika panjangnya berbeda. Pengurutan membutuhkan waktu O(n log n) dan, dalam sebagian besar bahasa, ruang O(n) untuk salinan karakternya. Pada n = 2 × 10^4, cara ini cepat, tetapi menghitung membutuhkan lebih sedikit pekerjaan.
Algoritma
- Jika panjang
sdantberbeda, kembalikanfalse. - Salin karakter dari setiap string ke dalam array.
- Urutkan kedua array.
- Kembalikan
truejika kedua array yang telah diurutkan sama, elemen demi elemen.
def isAnagram(s, t):
if len(s) != len(t):
return False
return sorted(s) == sorted(t)Hitung setiap huruf
Intuisi
Karena hanya 26 huruf yang dapat muncul, simpan satu penghitung untuk setiap huruf dalam array berisi 26 elemen, dengan indeks berupa kode karakter dikurangi kode a. Telusuri s sambil menambahkan 1 ke penghitung setiap huruf, lalu telusuri t sambil mengurangi 1.
Penghitung di bawah 0 berarti t menggunakan huruf itu lebih sering daripada s, jadi kamu bisa langsung berhenti. Untuk aabb dan abbb, nilai penghitungnya adalah a: 2, b: 2 setelah s; huruf b ketiga dari t membuat nilai b menjadi -1, lalu kamu mengembalikan false.
Jika tidak ada penghitung yang bernilai negatif, jumlahnya cocok. Panjang kedua string sama, jadi jumlah semua penghitung adalah 0 setelah kedua penelusuran; jika tidak ada yang negatif, nilai positif tidak akan memiliki nilai lain untuk menyeimbangkannya, sehingga semuanya bernilai 0. Itulah sebabnya pemeriksaan panjang merupakan bagian dari pembuktian, bukan jalan pintas.
Setiap string dibaca satu kali, dengan waktu O(n), dan array menyimpan 26 angka berapa pun panjangnya, dengan ruang tambahan O(1).
Algoritma
- Jika panjang
sdantberbeda, kembalikanfalse. - Buat array berisi 26 angka nol.
- Untuk setiap huruf dalam
s, tambahkan 1 ke pencacahnya. - Untuk setiap huruf dalam
t, kurangi 1 dari pencacahnya. Jika nilainya turun di bawah 0, kembalikanfalse. - Kembalikan
true.
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
Jebakan dan kasus tepi
- Membandingkan kumpulan huruf.
aabbdanabbbsama-sama hanya menggunakanadanb, tetapi keduanya bukan anagram. - Memeriksa apakah setiap huruf dalam
tmuncul di suatu tempat dalamstanpa mencoretnya.aabdanabblolos pemeriksaan itu untuk kedua arah. - Melewatkan pemeriksaan panjang dalam versi penghitungan. Dengan
s = abdant = a, tidak ada pencacah yang nilainya kurang dari 0, sehingga kode keliru mengembalikantrue. - Mengindeks array pencacah menggunakan kode karakter mentah. Nilai
aadalah 97, jauh melewati akhir array berukuran 26. Kurangi dahulu dengan kodea, lalu di Lua dan R tambahkan 1 karena array-nya dimulai dari 1.
Pertanyaan yang sering diajukan3
Berapa kompleksitas waktu Valid Anagram?
Menghitung huruf membutuhkan waktu O(n) dan ruang tambahan O(1), karena array penghitung memiliki 26 entri, berapa pun panjang string-nya. Mengurutkan kedua string membutuhkan waktu O(n log n) dan biasanya ruang O(n) untuk salinan yang sudah diurutkan.
Apakah lebih baik mengurutkan atau menghitung saat memeriksa anagram?
Menghitung lebih cepat secara teoretis, O(n) dibandingkan O(n log n), dan prosesnya dapat berhenti segera setelah satu huruf digunakan terlalu sering. Pengurutan lebih singkat untuk ditulis dan berfungsi untuk alfabet apa pun tanpa perubahan. Dalam wawancara, sebutkan pengurutan terlebih dahulu, lalu tingkatkan solusinya dengan menghitung.
Mengapa menggunakan satu array penghitung alih-alih dua?
Dua array, masing-masing untuk satu string, juga bisa digunakan: hitung setiap string, lalu bandingkan array-nya. Satu array yang nilainya bertambah untuk s dan berkurang untuk t menggunakan setengah memori dan memungkinkan kamu mengembalikan false begitu sebuah penghitung menjadi negatif, tanpa perulangan perbandingan terakhir.
Soal serupa
Soal yang memakai ide yang sama. Mengerjakan dua atau tiga di antaranya membuat polanya melekat.
def isAnagram(s, t):
# Tulis kodemu di siniTes #1
Tes #2
Tes #3
Argumen
s = "listen" t = "silent"
Output yang diharapkan
true