Hari ini kami akan memulakan gambaran keseluruhan kami tentang konsep yang digunakan untuk menangani pelbagai masalah algoritma. Pemahaman tentang konsep tertentu mungkin memberi anda intuisi dari sudut mana untuk mula memikirkan penyelesaian yang berpotensi.
Terdapat konsep yang berbeza tetapi tidak terlalu banyak di luar sana. Hari ini saya akan melaburkan perhatian anda ke dalam konsep tingkap gelongsor.
Konsep tingkap gelongsor sedikit lebih terlibat, berbanding pada pandangan pertama. Saya akan menunjukkannya dalam contoh praktikal. Buat masa ini, perlu diingat, idea konsep ialah kita akan mempunyai beberapa tetingkap yang perlu kita alihkan. Mari kita mulakan dari contoh segera.
Andaikan anda mempunyai tatasusunan integer dan saiz subarray yang dipratakrifkan. Anda diminta mencari subarray (aka tetingkap) sedemikian yang mana jumlah nilainya akan menjadi maksimum antara lain.
array = [1, 2, 3] window_size = 2 # conceptually subarray_1 = [1, 2] --> sum 3 subarray_2 = [2, 3] --> sum 5 maximum_sum = 5
Nah, kelihatan agak mudah:
(1) tingkap gelongsor saiz 2
(2) 2 subarray
(3) kira jumlah setiap
(4) cari maks antara mereka
Mari kita laksanakan.
def foo(array: List[int], size: int) -> int: maximum = float("-inf") for idx in range(size, len(array)+1): left, right = idx-size, idx window = array[left:right] maximum = max(maximum, sum(window)) return maximum
Nampaknya kami baru sahaja menggunakan konsep tingkap gelongsor dengan cekap. Sebenarnya, tidak betul-betul. Kita mungkin mendapat "bukti" itu dengan memahami kerumitan masa penyelesaian.
Kerumitannya ialah O(l)*O(w), dengan l ialah jumlah tetingkap dalam tatasusunan dan w ialah jumlah elemen dalam tetingkap. Dalam erti kata lain, kita perlu merentasi l tingkap dan untuk setiap tetingkap l-th kita perlu mengira jumlah elemen w.
Apa yang dipersoalkan di sini? Mari kita gambarkan secara konseptual lelaran untuk menjawab soalan.
array = [1, 2, 3, 4] window_size = 3 iterations 1 2 3 4 5 |___| |___| |___|
Jawapannya ialah walaupun kita meluncurkan tatasusunan, pada setiap lelaran kita perlu "mengira semula" elemen k-1 yang telah dikira pada lelaran sebelumnya.
Pada asasnya, pandangan ini sepatutnya mencadangkan kita untuk bertanya soalan:
"adakah cara untuk memanfaatkan pengiraan daripada langkah sebelumnya?"
Jawapannya ya. Kita boleh mendapatkan jumlah elemen tetingkap dengan menambah dan menolak yang pertama dan seterusnya selepas elemen tetingkap. Biar saya masukkan idea ini ke dalam kod.
def foo(array: List[int] = None, size: int = 0) -> int window_start, max_, window_sum_ = 0, float("-inf"), 0 for window_end in range(len(array)): if window_end > size - 1: window_sum_ -= array[window_start] window_start += 1 window_sum_ += array[window_end] max_ = max(max_, window_sum_) return max_ assert foo(array=[1, 2, 3, 4], size=3) == 9
Di sini kita mungkin melihat, apabila kita membina subarray panjang saiz, kita mula menolak elemen pertama daripada jumlah tetingkap, perkara yang membolehkan kita menggunakan semula pengiraan dari langkah sebelumnya.
Sekarang, kami mungkin mengatakan kami menggunakan konsep tetingkap gelongsor dengan cekap sedangkan kami mendapat bukti yang menyemak kerumitan masa, yang dikurangkan daripada O(l*w) kepada O(l), dengan l ialah jumlah tetingkap yang akan kami gelongsor.
Idea utama yang ingin saya ketengahkan, konsep tetingkap gelongsor bukan hanya tentang menghiris yang boleh dilelang dengan tetingkap saiz tertentu.
Izinkan saya memberi anda beberapa masalah, di mana kita akan belajar cara mengesan masalah itu mungkin melibatkan konsep tetingkap gelongsor serta apa sebenarnya yang mungkin anda lakukan dengan tingkap itu sendiri.
Memandangkan saya bercakap di sini hanya tentang konsep, saya akan melangkau "cara mengira sesuatu di dalam tetingkap".
Masalah satu
Diberi tatasusunan, cari purata semua subarray bersebelahan saiz K di dalamnya.
Bagus, sekarang kita mungkin mentakrifkan pendekatan dengan cara: lelaran ke atas tatasusunan input dengan tetingkap saiz K. Pada setiap lelaran kira purata tetingkap ...
Masalah dua
Diberi tatasusunan nombor positif dan nombor positif K, cari jumlah maksimum mana-mana subray bersebelahan saiz K.
Sekarang: lintasi tatasusunan input dengan tetingkap bersaiz K. Pada setiap lelaran kira jumlah tetingkap ...
Masalah ketiga
Diberi tatasusunan nombor positif dan nombor positif S, cari panjang subarray bersebelahan terkecil yang jumlahnya lebih besar daripada atau sama dengan S.
ここで、アプローチを次のように定義します。「まず、入力配列を反復処理し、条件を満たす最初のウィンドウを構築します (合計が S に対して >= である)。完了したら、ウィンドウを移動し、ウィンドウの開始と管理を行います」終わります…」
問題 4文字列が与えられた場合、その中で K 個以下の異なる文字を含む最長の部分文字列の長さを見つけます。
各整数が果樹を表す整数の配列が与えられた場合、2 つのバスケットが与えられ、目標は各バスケットに最大数の果物を入れることです。唯一の制限は、各バスケットに 1 種類のフルーツのみを入れることです。それほど明白ではないようです。まず条件を単純化しましょう。どのツリーからでも開始できますが、一度開始したツリーをスキップすることはできません。各木から 1 つの果物を収穫できなくなるまで収穫します。つまり、3 番目の果物の種類から収穫する必要があるときに停止します。
両方のバスケット内の果物の最大数を返す関数を作成します。
入力配列があります。配列には 2 つの異なる数字 (バケット) のみが含まれる場合があります。長さが最大になるような連続した部分配列を見つけるように求められます。これで、スライディング ウィンドウのコンセプトを使用できる可能性があることが簡単にわかりました。
文字列とパターンが与えられた場合、その文字列にパターンの順列が含まれているかどうかを調べます。まず、オリジナルとパターンの2つの弦があります。何らかの方法でオリジナルとパターンを比較したことがわかり、そのアイデアに至ったので、パターンのサイズのウィンドウを構築し、さらに順列チェックを実行する必要があります。つまり、スライディング ウィンドウのコンセプトを使用する可能性があります。 アウトロ スライディング ウィンドウを扱うときは、次の質問に留意してください:
Atas ialah kandungan terperinci Siri Bercakap dengan Anda #2. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!