iT邦幫忙

2022 iThome 鐵人賽

DAY 18
0

在古早時代,如果製作遊戲時要使用動畫,有時候一張一張的圖片讀取進來,電腦的效能無法支撐.所以在比較爛的電腦上就會一卡一卡的不滑順.這個時候就會改為使用滑動視窗動畫來呈現.

這個作法是這樣的,把所有動畫都放在一張大圖上面,但是用一個小視窗當成呈現的區塊.而其他區塊就不呈現在使用者面前.當要更新動畫內容的時候,不用重新載入圖片,而是只要移動小視窗,這樣就會自行更新呈現的樣子,完成動畫效果.

https://github.com/officeyuli/itHome2022/raw/main/day17/20160227112102240.png

(比如說上面這張圖要展示爆炸的動畫,只要用穩定的速度從(2,2)格移動到(2,5)格,看起來就有那麼一回事)

而滑動視窗演算法也像是這樣,我們維護一個不停移動的視窗,然後更新答案

這個演算法的思考大概如下

fun windowAlgo(s:Array<T>){
    var left = 0
    var right = 0
    while(right<s.size){
        //增大視窗
        window.add(s[right])
        right++
        while ( window needs shrink){//檢查需要縮小視窗
            //縮小視窗
            window.remove(s[left])
            left++
        }
    }
}

這種演算法的時間複雜度是O(N),比字串暴力演算有效的多.

其實困難的不是演算法的思路,而是細節很多.例如如何讓視窗增加元素,如何縮小視窗,在滑動的哪個階段更新結果.即使明白這些細節,也很容易有bug,而且bug還很難找.

所以我們將思考擴寫成框架

fun slidingWindow(s: String, t: String) {
    val need: HashMap<Char, Int> = HashMap()
    val window: HashMap<Char, Int> = HashMap()
    t.forEach { need[it] = 1 }
    
    var left = 0
    var right = 0
    var valid = 0
    while(right<s.length){
        //c是即將移入視窗的字元
        val c = s[right]
        //右移視窗
        right++
        //進行視窗內的一系列更新
        ...
        while(whindow need shrink){
            //d 是即將移出視窗的字元
            val d = s[left]
            //左移視窗
            left++
            //進行視窗內的一系列更新
            ...
        }
    }

}

其中...代表要更新資料的地方,根據題目填入邏輯即可.而且這兩處的操作,會分別是右邊進入以及左邊移除的操作,而之後會發現這兩者完全相同.


上一篇
Day 17 :二分演算法的左右邊界問題
下一篇
Day 19 :最小覆蓋字串
系列文
從零開始的LeetCode生活,使用Kotlin學習刷題30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言