828. Count Unique Characters of All Substrings of a Given String
題目網址:https://leetcode.cn/problems/count-unique-characters-of-all-substrings-of-a-given-string/
題意:定義一函數
countUniqueChars(s)
返回 strings
中只出現一次的 char 之個數。e.g.
s = "LEETCODE"
, 其中L
、T
、C
、O
、D
皆只出現過一次, 因此countUniqueChars(s) = 5
。今給一 string
s
, 返回countUniqueChars(t)
的總和, 其中t
是s
的 substring。注意:
- 有些 substring 是會重複的, 計算時也必須算上這些重複的 substring(也就是說, 統計
s
所有 substring 中只出現一次的 char)。s
僅由大寫英文所組成。
Solution 1:
想法:與其計算所有 substring 中的 unique char 個數, 不如計算單一 char 在哪些 substring 是 unique char, 最後做加總即為所求
- 考慮
s = XAXAXXAX
並專注於使第二個A
成為 unique char- 我們可以取
XA(XAXX)AX
, 其中()
中間的範圍就是符合條件的 substring 範圍- 因此, 能使第二個
A
為 unique char 的總共有 6 種 substring
- 第二個
A
以左(不含A
)可取""
、X
這 2 種 substring- 第二個
A
以右(不含A
)可取""
、X
、XX
這 3 種 substring- 總共有
A
、AX
、AXX
和XA
、XAX
、XAXX
這 6 種 substring- 若想求
idx = i
的 char 為 unique char 的 substring 個數, 我們需要:
- 前一個跟
s[i]
相同的 char 的 idxj
- 後一個跟
s[i]
相同的 char 的 idxk
- substring 個數 =
(i - j) * (k - i)
- 因此, 我們要紀錄相同的 char 所有出現的位置
- 特殊情況:當
s
中和s[i]
相同的 char 不滿 2 個時, 也就是s[i]
找不到前一個相同的 char 或後一個相同的 char 時- 解決辦法:在每個 char 紀錄所有位置的開頭加上
1
, 且結尾加上n
, 這樣即便s
中沒有任何跟s[i]
相同的 char 也能計算 substring 個數 =(i + 1) * (n - i)
- e.g.
s = XA
, 可得到A
的idx = [-1, 1, 2]
A
以左(不含A
)可取""
、X
這 2 種 substringA
以右(不含A
)可取""
這 1 種 substring(1 + 1) * (2 - 1) = 2
, 總共有A
、XA
這 2 種 substring
class Solution { |
- time:$O(n)$ ➔ 遍歷
s
- space:$O(n)$ ➔
idx
紀錄s
中每個元素出現的位置
Solution 2:
想法:利用 Sliding window, 概念同 Solution 1, 只是計算
idx = i
之 substring 個數時, 只會用到前一個和後一個相同 char 的 idx, 故不需要一次紀錄所有相同 char 的位置
- 首先, 我們先將
last2idx
每個 char 的前兩個位置初始化為1, -1
(當前i
作為第三個位置)
➔ 貢獻值公式:(第二個位置 - 第一個位置) * (i - 第二個位置)
- 遍歷
s
中每個 char, 此時計算前一個 char(第二個位置)的貢獻值, 並累加到res
中- 假如當前 char 是首次出現, 因為前兩個 char 的出現位置都是
1
, 相減後為0
, 所以累加值還是0
- 然後更新
last2idx
中的值- 由於每次都是計算該 char 的前一個位置之貢獻值, 所以最後還需要一個 for loop 去計算每個 char 最後出現位置的貢獻值。由於最後一個 char 後面沒有相同 char 了, 故用
n
來替代其後一個 idx
class Solution { |
- time:$O(n)$ ➔ 遍歷
s
- space:$O(1)$ ➔ $O(26 \cdot 2)$, 因為
last2idx
只需常數空間
本部落格所有文章除特別聲明外,均採用 CC BY-NC-SA 4.0 許可協議。轉載請註明來自 Zako's Blog!
評論