Longest Consecutive Sequence
Kamu mendapatkan array bilangan bulat nums yang tidak memiliki urutan tertentu. Urutan berurutan adalah sekumpulan nilai x, x+1, x+2, dan seterusnya, yang masing-masing muncul di suatu tempat dalam nums. Kembalikan panjang urutan berurutan terpanjang. Nilai yang muncul lebih dari sekali dihitung satu kali.
Fungsi
- numsinteger-array
- bilangan bulat, dalam urutan apa pun, boleh berulang
- Mengembalikaninteger
- panjang rentetan terpanjang dari nilai berurutan yang terdapat dalam nums
Batasan
1 ≤ nums.length ≤ 104-109 ≤ nums[i] ≤ 109- Nilai dapat berulang. Posisi dalam array tidak penting, yang penting hanya nilai mana yang ada.
Contoh
- Input
- nums = [40, 4, 39, 1, 3, 2, 41]
- Output
- 4
- Penjelasan
1,2,3, dan4semuanya ada, membentuk rangkaian berisi 4 angka, meskipun tersebar di dalam array. Rangkaian lainnya, dari39hingga41, hanya memiliki 3 nilai.
- Input
- nums = [7, 3, 7, 5, 6, 5]
- Output
- 3
- Penjelasan
5,6, dan7membentuk deretan 3.7kedua dan5kedua tidak menambahkan apa pun, dan3tidak bisa bergabung karena4tidak ada.
- Input
- nums = [10, 30, 20]
- Output
- 1
- Penjelasan
- Tidak ada dua nilai yang selisihnya 1, jadi setiap perulangan hanya berisi satu nilai dan jawabannya adalah 1.
Pertanyaan lanjutan
Misalkan nilai datang satu per satu dan setelah setiap nilai kamu harus melaporkan perulangan terpanjang sejauh ini. Bisakah kamu menjaga jawaban tetap terkini dalam waktu rata-rata O(1) per nilai?
Petunjuk
Buka satu per satu. Setiap petunjuk mengungkap sedikit lebih banyak.
Coba setiap nilai sebagai angka pertama dalam suatu urutan, lalu hitung naik. Pertanyaan apa yang kamu ajukan berulang kali, dan berapa biaya setiap jawaban saat kamu mencarinya di array?
Pertanyaannya adalah "apakah
x+1ada di dalam array?". hash set menjawabnya dalam waktu konstan secara rata-rata, dan juga menghapus nilai yang berulang.Mulai menghitung hanya dari nilai
xyangx-1tidak ada dalam set. Dari sana, lanjutkan kex+1,x+2, dan seterusnya selama set memuatnya, lalu simpan langkah terpanjang. Setiap nilai kemudian hanya dilalui satu kali dalam satu langkah.
Solusi
Nilai-nilai dalam suatu rangkaian bisa berada di mana saja dalam array. Pengurutan menyusunnya dalam O(n log n). Hash set menjawab pertanyaan "apakah x+1 ada di sini?" dalam O(1), dan jika kamu hanya menghitung dari nilai-nilai yang x-1-nya tidak ada, setiap nilai dilewati satu kali: totalnya O(n).
Hitung maju dari setiap nilai dengan menelusuri array
Benar, tetapi tidak selesai pada tes terbesar
Intuisi
Anggap setiap nilai sebagai kemungkinan awal sebuah perulangan. Dari x, cari x+1 di dalam array, lalu x+2, sampai suatu nilai tidak ditemukan, lalu pertahankan hitungan terpanjang. Setiap perulangan memiliki nilai terkecil di nums, dan perulangan menelusuri seluruh rangkaian darinya.
Setiap pencarian membaca hingga n nilai, dan perulangan panjang ditelusuri kembali dari setiap anggotanya. Untuk 10^4 nilai yang membentuk satu rangkaian acak, penelusuran membutuhkan sekitar n²/2 = 5 × 10^7 langkah, dengan setiap pemindaian memeriksa rata-rata setengah array: sekitar 2.5 × 10^11 perbandingan.
Algoritma
- Tetapkan
bestke 0. - Untuk setiap nilai
startdalamnums, tetapkancurrentkestartdanlengthke 1. - Selama pemindaian
numsmenemukancurrent+1, tambahkan 1 kecurrentdanlength. - Simpan
lengthke dalambestjika nilainya lebih besar. - Kembalikan
best.
def longestConsecutive(nums):
best = 0
for start in nums:
current = start
length = 1
# "in" on a list reads it from the front until it finds the value.
while current + 1 in nums:
current += 1
length += 1
best = max(best, length)
return bestUrutkan, lalu hitung rangkaian
Intuisi
Pengurutan menempatkan nilai-nilai dari setiap perulangan secara berdampingan: [40, 4, 39, 1, 3, 2, 41] menjadi [1, 2, 3, 4, 39, 40, 41], lalu perulangan dibaca dari kiri ke kanan.
Telusuri nilai-nilai yang sudah diurutkan dan simpan panjang perulangan saat ini. Nilai yang lebih besar satu dari nilai sebelumnya akan memperpanjangnya. Nilai yang berulang tidak memperpanjang atau mengakhiri perulangan, jadi lewati nilai itu. Nilai lainnya memulai perulangan baru dengan panjang 1.
Pengurutan memerlukan biaya O(n log n) dan penelusuran memerlukan biaya O(n). Pengurutan di tempat tidak memerlukan array tambahan; bahasa yang mengurutkan salinan menggunakan memori O(n).
Algoritma
- Urutkan
numsdalam urutan menaik. - Tetapkan
bestdanrunke 1, karena array tidak pernah kosong. - Untuk setiap indeks
imulai dari 1, lewatinums[i]jika nilainya sama dengannums[i-1]. - Jika
nums[i]adalahnums[i-1]+1, tambahkan 1 kerun; jika tidak, tetapkanrunke 1. Simpanrundalambestjika nilainya lebih besar. - Kembalikan
best.
def longestConsecutive(nums):
nums.sort()
best = 1
run = 1
for i in range(1, len(nums)):
if nums[i] == nums[i - 1]:
continue # a repeat neither extends nor breaks the run
if nums[i] == nums[i - 1] + 1:
run += 1
else:
run = 1
best = max(best, run)
return bestHash set, menghitung hanya dari awal setiap perulangan
Intuisi
Untuk setiap nilai dalam hash set, pemeriksaan keanggotaan memerlukan biaya rata-rata O(1), dan nilai yang berulang digabungkan menjadi satu entri.
Menelusuri dari setiap nilai tetap akan mengulangi pekerjaan: dalam rangkaian 1, 2, 3, 4, kamu akan menempuh 3 langkah dari 1, 2 langkah dari 2, dan 1 langkah dari 3. Jadi, telusuri hanya dari nilai pertama dalam suatu rangkaian, yaitu nilai x yang x-1 tidak ada. Dalam contoh 1, hanya 1 dan 39 yang memenuhi syarat, sehingga menghasilkan rangkaian dengan panjang 4 dan 3.
Setiap nilai termasuk dalam satu rangkaian dan hanya dilalui oleh penelusuran rangkaian tersebut, sehingga seluruh penelusuran paling banyak menempuh n langkah. Dengan satu pemeriksaan untuk setiap nilai, total waktunya O(n) dan penggunaan memorinya O(n) untuk set tersebut.
Algoritma
- Masukkan setiap nilai dari
numske dalam hash setvalues, lalu aturbestke 0. - Untuk setiap nilai
xdalam set tersebut, lewati jikax-1ada di dalam set: nilai itu bukan nilai pertama dalam deretnya. - Jika tidak, atur
endkexdan tambahkan 1 selamaend+1ada di dalam set. - Simpan
end-x+1ke dalambestjika nilainya lebih besar. - Kembalikan
best.
def longestConsecutive(nums):
values = set(nums)
best = 0
for value in values:
# Only a value with no left neighbour starts a run.
if value - 1 in values:
continue
end = value
while end + 1 in values:
end += 1
best = max(best, end - value + 1)
return best
Jebakan dan kasus tepi
- Menganggap nilai yang berulang sebagai celah atau langkah setelah pengurutan. Dalam
[1, 2, 2, 3], mengatur ulang rangkaian pada2kedua menghasilkan 2, sedangkan menghitungnya sebagai langkah menghasilkan 4. Jawabannya adalah 3. - Memulai
bestdari 0 dalam penelusuran terurut dan hanya memperbaruinya di dalam perulangan. Array yang berisi satu nilai akan menghasilkan 0, bukan 1. - Menelusuri setiap nilai dalam set, bukan hanya awal rangkaian. Satu rangkaian yang terdiri dari
10^4nilai membutuhkan5 × 10^7langkah. - Melakukan perulangan pada
nums, bukan pada set. Jika nilai pertama dari rangkaian berisi 2.500 nilai muncul sebanyak 2.000 kali, rangkaian tersebut ditelusuri 2.000 kali. - Mengindeks array berdasarkan nilai. Nilainya mencapai
±10^9, jadi diperlukan2 × 10^9entri.
Pertanyaan yang sering diajukan3
Berapa kompleksitas waktu dari Longest Consecutive Sequence?
Solusi dengan hash set berjalan dalam waktu rata-rata O(n) dengan memori tambahan O(n). Pengurutan dan penghitungan membutuhkan waktu O(n log n). Mencari array untuk setiap nilai berikutnya tanpa set membutuhkan waktu hingga O(n³).
Bisakah kamu menyelesaikan Urutan Berurutan Terpanjang tanpa memori tambahan?
Ya, jika kamu boleh mengurutkan ulang input: urutkan langsung di tempat dan hitung kelompok dalam satu lintasan, dengan melewati pengulangan. Cara ini menggunakan memori tambahan O(1), tetapi membutuhkan waktu O(n log n). Solusi O(n) membutuhkan hash set.
Bisakah union-find menyelesaikan Longest Consecutive Sequence?
Ya. Jadikan setiap nilai yang berbeda sebagai set, gabungkan x dengan x+1 jika keduanya ada, lalu kembalikan ukuran set terbesar. Algoritma ini berjalan dalam waktu mendekati O(n), tetapi memerlukan pemetaan nilai ke indeks, tautan parent, dan ukuran, sedangkan penelusuran hash set hanya memerlukan satu set.
Soal serupa
Soal yang memakai ide yang sama. Mengerjakan dua atau tiga di antaranya membuat polanya melekat.
def longestConsecutive(nums):
# Tulis kodemu di siniTes #1
Tes #2
Tes #3
Argumen
nums = [40, 4, 39, 1, 3, 2, 41]
Output yang diharapkan
4