Missing Number
Kamu mendapatkan list nums yang berisi n bilangan bulat berbeda, masing-masing antara 0 dan n. Rentang dari 0 hingga n memuat n+1 bilangan, jadi tepat satu bilangan tidak ada di dalam list. Kembalikan bilangan yang hilang tersebut.
Fungsi
- numsinteger-array
- n bilangan bulat berbeda dari rentang 0 hingga n, dalam urutan apa pun
- Mengembalikaninteger
- satu angka dari 0 sampai n yang tidak ada di nums
Batasan
n == nums.length1 ≤ n ≤ 1040 ≤ nums[i] ≤ n- Semua nilai dalam
numsberbeda.
Contoh
- Input
- nums = [4, 2, 0, 1]
- Output
- 3
- Penjelasan
- list ini memiliki 4 nilai, jadi rentangnya dari 0 sampai 4. list ini berisi 0, 1, 2, dan 4, sedangkan 3 adalah satu-satunya angka yang tidak memiliki pasangan.
- Input
- nums = [1]
- Output
- 0
- Penjelasan
- Dengan satu nilai, rentangnya adalah 0 dan 1. List tersebut berisi 1, jadi 0 tidak ada.
- Input
- nums = [0, 1, 2]
- Output
- 3
- Penjelasan
- Semua angka di bawah 3 tersedia, jadi angka yang hilang adalah 3, batas atas rentang tersebut. Angka itu bukan indeks list.
Pertanyaan lanjutan
Jika list sudah terurut, bisakah kamu menemukan angka yang hilang dalam waktu O(log n) dengan pencarian biner?
Petunjuk
Buka satu per satu. Setiap petunjuk mengungkap sedikit lebih banyak.
Kamu tahu persis angka yang harus dimuat oleh list: setiap bilangan bulat dari
0hinggan. Apakah ada satu angka yang bisa kamu hitung untuk rentang penuh itu dan bandingkan dengan angka yang sama yang dihitung untuk list?Bilangan bulat dari
0sampainjika dijumlahkan hasilnyan(n+1)/2, dan jumlah nilai dalam list lebih kecil tepat sebesar nilai yang hilang. XOR bekerja dengan cara yang sama tanpa risiko overflow, karena nilai yang di-XOR dengan dirinya sendiri menghasilkan0.Telusuri list satu kali dengan XOR berjalan. Mulai dari
n, lalu pada setiap indeksi, lakukan XOR denganidannums[i]. Setiap angka yang muncul dua kali akan saling meniadakan, dan angka yang hilang akan tersisa.
Solusi
Kamu tahu isi list yang seharusnya: setiap bilangan bulat dari 0 hingga n. Ringkas rentang penuh dan list menjadi satu nilai ringkasan masing-masing, yaitu jumlah atau XOR, dan selisih antara keduanya adalah angka yang hilang. Cara ini hanya membutuhkan satu kali penelusuran dan tidak membutuhkan memori tambahan.
Periksa setiap kandidat
Benar, tetapi tidak selesai pada tes terbesar
Intuisi
Periksa kandidat 0 sampai n secara berurutan dan telusuri list untuk setiap kandidat. Setiap angka dalam rentang tersebut ada di dalam list atau merupakan jawabannya, jadi kandidat pertama yang tidak ditemukan adalah angka yang hilang.
Setiap kandidat memerlukan pemindaian hingga n nilai. Dengan n = 10^4 dan celahnya berada di dekat angka teratas, jumlahnya sekitar 5 × 10^7 perbandingan.
Algoritma
- Ulangi
candidatedari0hinggan, termasukn. - Pindai
numsuntuk mencari nilai yang sama dengancandidate. - Jika pemindaian menemukannya, lanjutkan ke kandidat berikutnya.
- Jika pemindaian berakhir tanpa kecocokan, kembalikan
candidate.
def missingNumber(nums):
n = len(nums)
for candidate in range(n + 1):
# "in" on a list scans it from the start: O(n) per candidate.
if candidate not in nums:
return candidate
return -1Kurangi jumlah tersebut dari jumlah yang diharapkan
Intuisi
Jumlah angka 0 sampai n adalah n(n+1)/2. list tersebut berisi semua angka itu kecuali satu angka, jadi jumlahnya kurang tepat sebesar angka tersebut. Untuk [4, 2, 0, 1], jumlah rentangnya adalah 4 × 5 / 2 = 10 dan jumlah list adalah 7, sehingga selisihnya 3.
Satu kali penelusuran menjumlahkan seluruh isi list: waktu O(n) dan satu total berjalan.
Algoritma
- Misalkan
nadalah panjangnums. - Hitung jumlah total
n(n+1)/2. - Jumlahkan semua nilai dalam
nums. - Kembalikan jumlah total dikurangi jumlah nilai dalam list.
def missingNumber(nums):
n = len(nums)
expected = n * (n + 1) // 2
return expected - sum(nums)XOR indeks dengan nilainya
Intuisi
XOR membatalkan pasangan: a ^ a adalah 0, a ^ 0 adalah a, dan urutannya tidak berpengaruh. Lakukan XOR pada indeks 0 hingga n bersama dengan nilainya. Sebuah angka dalam list muncul sekali sebagai indeks dan sekali sebagai nilai, jadi keduanya saling membatalkan. Angka yang hilang hanya muncul sebagai indeks, jadi angka itulah yang tersisa. Perulangan mengunjungi indeks 0 hingga n-1, jadi mulai hasilnya dari n.
Untuk [4, 2, 0, 1]: mulai dari 4, lalu lakukan XOR dengan 0 dan 4, 1 dan 2, 2 dan 0, 3 dan 1. Semua angka kecuali 3 muncul dua kali, jadi 3 yang tersisa. Nilai yang terus diperbarui tidak pernah menggunakan bit lebih banyak daripada n, jadi nilainya tidak bisa mengalami overflow.
Algoritma
- Atur
resultken, panjangnums. - Untuk setiap indeks
i, lakukan XOR padaresultdenganidannums[i]. - Kembalikan
result.
def missingNumber(nums):
# Start with n, the one index the loop below never reaches.
result = len(nums)
for i, value in enumerate(nums):
result ^= i ^ value
return result
Jebakan dan kasus tepi
- Lupa bahwa
nsendiri bisa hilang. Dalam[0, 1, 2], jawabannya adalah 3, yang bukan indeks; versi XOR harus dimulai darin. - Menggunakan ukuran rentang yang salah. Rentang
0hingganmemuatn+1angka, jadi jumlah totalnya adalahn(n+1)/2, bukan(n-1)n/2. - Memulai pencarian dari 1. Dalam
[1], jawabannya adalah 0. - Terjadi overflow pada versi penjumlahan untuk input yang lebih besar. Dalam aritmetika 32-bit,
n(n+1)mengalami overflow saatnmelewati sekitar 46,000. Gunakan aritmetika 64-bit atau XOR.
Pertanyaan yang sering diajukan3
Berapa kompleksitas waktu dari Missing Number?
Solusi penjumlahan dan XOR sama-sama berjalan dalam waktu O(n) dengan ruang ekstra O(1): keduanya membaca setiap nilai satu kali dan menyimpan satu angka. Mencari setiap kandidat di dalam list membutuhkan O(n²), sedangkan mengurutkan terlebih dahulu untuk menemukan celah membutuhkan O(n log n).
Haruskah kamu menggunakan rumus penjumlahan atau XOR?
Keduanya memerlukan satu kali pemindaian dan memori konstan. Penjumlahan lebih mudah dijelaskan, tetapi hasil perkalian sementaranya memerlukan bilangan bulat 64-bit setelah n melewati sekitar 46.000. XOR tidak pernah mengalami overflow.
Bisakah kamu menyelesaikan Missing Number dengan hash set?
Ya. Masukkan setiap nilai ke dalam set, lalu periksa 0 hingga n dan kembalikan angka pertama yang tidak ada di dalam set. Cara ini berjalan dalam waktu O(n), tetapi menggunakan memori tambahan O(n), yang dihindari oleh metode penjumlahan dan XOR.
Soal serupa
Soal yang memakai ide yang sama. Mengerjakan dua atau tiga di antaranya membuat polanya melekat.
def missingNumber(nums):
# Tulis kodemu di siniTes #1
Tes #2
Tes #3
Argumen
nums = [4, 2, 0, 1]
Output yang diharapkan
3