題目
給定一個整數(shù)數(shù)組 nums,處理以下類型的多個查詢:
計算索引 left 和 right(包含 left 和 right)之間的 nums 元素的 和,其中 left <= right
實(shí)現(xiàn) NumArray 類:
-
NumArray(int[] nums)使用數(shù)組nums初始化對象 -
int sumRange(int i, int j)返回數(shù)組nums中索引left和right之間的元素的 總和,包含left和right兩點(diǎn)(也就是nums[left] + nums[left + 1] + ... + nums[right])
示例 1:
- 輸入:
["NumArray", "sumRange", "sumRange", "sumRange"]
[[[-2, 0, 3, -5, 2, -1]], [0, 2], [2, 5], [0, 5]]- 輸出:
[null, 1, -1, -3]
- 解釋:
NumArray numArray = new NumArray([-2, 0, 3, -5, 2, -1])
numArray.sumRange(0, 2); // return 1 ((-2) + 0 + 3)
numArray.sumRange(2, 5); // return -1 (3 + (-5) + 2 + (-1))
numArray.sumRange(0, 5); // return -3 ((-2) + 0 + 3 + (-5) + 2 + (-1))
方法一:前綴和
思路及解法
最樸素的想法是存儲數(shù)組 的值,每次調(diào)用
時,通過循環(huán)的方法計算數(shù)組
從下標(biāo)
到下標(biāo)
范圍內(nèi)的元素和,需要計算
個元素的和。由于每次檢索的時間和檢索的下標(biāo)范圍有關(guān),因此檢索的時間復(fù)雜度較高,如果檢索次數(shù)較多,則會超出時間限制。
由于會進(jìn)行多次檢索,即多次調(diào)用 ,因此為了降低檢索的總時間,應(yīng)該降低
的時間復(fù)雜度,最理想的情況是時間復(fù)雜度
。為了將檢索的時間復(fù)雜度降到
,需要在初始化的時候進(jìn)行預(yù)處理。
注意到當(dāng) 時,
可以寫成如下形式:
由此可知,要計算 ,則需要計算數(shù)組
在下標(biāo)
和下標(biāo)
的前綴和,然后計算兩個前綴和的差。
如果可以在初始化的時候計算出數(shù)組 在每個下標(biāo)處的前綴和,即可滿足每次調(diào)用
的時間復(fù)雜度都是
。
具體實(shí)現(xiàn)方面,假設(shè)數(shù)組 的長度為
,創(chuàng)建長度為
的前綴和數(shù)組
,對于
都有
,則當(dāng)
時,
表示數(shù)組
從下標(biāo)
到下標(biāo)
的前綴和。
將前綴和數(shù)組 的長度設(shè)為
的目的是為了方便計算
,不需要對
的情況特殊處理。此時有:
代碼
class NumArray {
var sums: [Int]
init(_ nums: [Int]) {
sums = Array.init(repeating: 0, count: nums.count + 1)
for i in 0..<nums.count {
sums[i + 1] = sums[i] + nums[i]
}
}
func sumRange(_ left: Int, _ right: Int) -> Int {
return sums[right + 1] - sums[left]
}
}
復(fù)雜度分析
時間復(fù)雜度:初始化
,每次檢索
,其中
是數(shù)組
的長度。
初始化需要遍歷數(shù)組計算前綴和,時間復(fù)雜度是
。
每次檢索只需要得到兩個下標(biāo)處的前綴和,然后計算差值,時間復(fù)雜度是。
空間復(fù)雜度:
,其中
是數(shù)組
的長度。需要創(chuàng)建一個長度為
的前綴和數(shù)組。