LeetCode #30 Substring with Concatenation of All Words - 刷題之旅
1 題目描述
會提供words跟s,要求找出s中所有words的連續子串的起始索引。
2 解法
2.1 一個個慢慢找
- 我們從i=0開始檢查,取
s[i:i+word_len]
叫做word(圖片橘色部分) - 有一個
word_dic
負責紀錄要求,也就是words中的word的數量 - 有一個
seen
負責紀錄已經看過且是word_dic
的word,可以用來與word_dic
比較判斷當前的window是否滿足狀況
擴展window的條件:
- 基本上擴展window的時機點是透過
count
的移動來移動window,但是何時要移動count
呢? - 當前的word是合法的條件?
- 當前的
word
是word_dic
中的word - 當前的
seen[word]
小於word_dic[word]
- 當前的
- word 合法之後要做哪些工作?
count
要+1,count用來計算start
的位置以及判斷是否滿足word_dic
的數量要求
紀錄i的時機
- 當我們發現滿足
count
等於len(words)
時,代表我們找到了一個合法的window,這時候要紀錄i
的位置- 因為
count
只會在word合法的時候+1,所以當count
等於len(words)
時,代表我們找到了一個合法的window,這時候要紀錄start
的位置
- 因為
停止當前window的條件是:
- 何時檢查要停下來?
- 如果
word
不在word_dic
中,或者seen[word]
大於word_dic[word]
,就要停下來,換下一個i
開始檢查- 舉例來說
foofoobar
可以組成seen={foo:2, bar:1}
,但是我們要的是word_dic={foo:1, bar:1}
foo
的數量已經超過了,所以當前的window不合法,也就是i
是不合法的,我們要往下一個開始檢查。
- 舉例來說
- 如果
- 停下來後要做哪些事情?
count
要歸零,seen
要清空,重新來過i
要+1,開始下一個window的檢查
i
要檢查到哪裡?i
要檢查到s
的長度減去word_len * words_count
- 因為如果
i
到len(s)-word_len * words_count
這裡都沒有找到合法的window,那麼後面的window也不可能找到合法的window,因為後面的長度已經不夠湊出words
的長度了
1 | """ |
2.2 跳躍式尋找
我們發現每次檢查的時候都是以word_len
為單位去尋找,如果word_len=3
我們是不是就可以歸類出以上情況。
以i=0為單位去檢查
- 從上圖可以發現,以三個三個為單位,如果發現滿足,就透過j移動到下一個word
- 如果發現當前的word不在
word_dic
裡面,表示這個start
肯定不合格- 所以我們要移動
start
到下一個word的位置 - 清空
seen
,count
重新開始
- 所以我們要移動
- 如果發現相同word的數量太多時,我們可以透過縮window移除重複的word
- 因為移除window的word,所以移動
start
到下一個位置 - 減少
count
的數量 - 減少
seen[first_word_in_window]
的數量
- 因為移除window的word,所以移動
1 | """ |
3 結論
這題我真的想了很久…真的有Hard的程度,最一開始能想到的是從i開始慢慢往下移動去檢查的,但是會TLE,後來看了解答才知道可以跳躍式的去檢查,這樣就可以避免TLE了。
參考資料
本部落格所有文章除特別聲明外,均採用 CC BY-NC-SA 4.0 許可協議。轉載請註明來自 Shannon's Blog 🐟 技術 | 生活 | 旅行! 如果你覺得我的文章有幫助,希望你可以到我的 github 給我一個 star ⭐️ Shannon Blog Repo
評論