327. Count of Range Sum
題目網址:https://leetcode.cn/problems/count-of-range-sum/
題意:給一整數 array
nums
以及兩個整數lower
和upper
。求nums
中, 值位於[lower, upper]
之區間和個數。區間和
S(i, j)
表示在nums
中, idx 從i
到j
中的區間之和, 包含i
和j
(i
≤j
)。
Solution:
想法:利用 Prefix Sum + Binary Search + Merge Sort, 類似 303. Range Sum Query - Immutable。
presum[0]
必須為0
, 若我們想求一區間和S(i, j)
可看做是prefix[j + 1] - prefix[i]
我們先考慮以下的問題:
給兩個升序的 array
n1
和n2
, 找出所有(i, j)
滿足 :n2[j] - n2[i] ∈ [lower,upper]
- 我們在
n2
中使用兩個 ptrleft
和right
, 初始皆為n2
的起始位置。- 考慮
n1
的第一個元素
- 將
left
不斷右移, 直到n2[left] ≥ n1[0] + lower
為止
➔ 此時,left
以及其右邊元素皆 ≥n1[0] + lower
- 將
right
不斷右移, 直到n2[right] > n1[0] + upper
為止
➔ 此時,right
的左邊元素皆≤ n1[0] + upper
- 得到區間
[left, right)
中所有的j
皆滿足 :n2[j] - n1[0] ∈ [lower,upper]
- 接著考慮
n1
的第二個元素, 依此類推, 遍歷完n1
後可得到所有符合條件的 (i, j) 之數量但
presum
不保證是升序的, 因為nums[i]
有可能為負數, 因此採用 Merge Sort 來解決此問題
- 首先, 我們將 presum 的元素都拆成一個一組, 然後開始兩兩合併
- 合併的過程中, 會先遍歷左區間所有的idx
i
, 然後到右區間去找符合條件的 idxj
之個數
找到後, 合併兩區間, 並由小到大排序, 將問題轉換成上面討論的問題e.g.
nums = [-2, 5, -1]
➔presum = [0, -2, 3, 2]
[0]、[-2]
合併時, 左區間元素 = 0, 右區間x = 1, y = 2
➔ 得到一組解[3]、[2]
合併時, 左區間元素 = 3, 右區間x = 3, y = 4
➔ 得到一組解[-2, 0]、[2, 3]
合併時
- 左區間第一個元素 = -2, 右區間
x = 2, y = 2
➔ 沒有滿足條件之j
- 左區間第一個元素 = 0, 右區間
x = 2, y = 3
➔ 得到一組解
class Solution { |
- time:$O(n \cdot log(n))$ ➔ $T(n) = 2 \cdot T(\dfrac{n}{2}) + O(n)$ 利用 Master theorem 計算得到
- $2 \cdot T(\dfrac{n}{2})$:遞迴左、右區間
- $O(n)$:merge 左、右區間並做 sorting
- space:$O(n)$ ➔ $O(log(n)) + O(n)$
- $O(log(n))$:遞迴深度
- $O(n)$:每層遞迴產生的
sorted
長度不超過n
本部落格所有文章除特別聲明外,均採用 CC BY-NC-SA 4.0 許可協議。轉載請註明來自 Zako's Blog!
評論