LeetCode中等题之区域和检索 - 数组可修改
題目
給你一個數組 nums ,請你完成兩類查詢。
其中一類查詢要求 更新 數組 nums 下標對應的值
另一類查詢要求返回數組 nums 中索引 left 和索引 right 之間( 包含 )的nums元素的 和 ,其中 left <= right
實現 NumArray 類:
NumArray(int[] nums) 用整數數組 nums 初始化對象
void update(int index, int val) 將 nums[index] 的值 更新 為 val
int sumRange(int left, int right) 返回數組 nums 中索引 left 和索引 right 之間( 包含 )的nums元素的 和 (即,nums[left] + nums[left + 1], …, nums[right])
示例 1:
輸入:
[“NumArray”, “sumRange”, “update”, “sumRange”]
[[[1, 3, 5]], [0, 2], [1, 2], [0, 2]]
輸出:
[null, 9, null, 8]
解釋:
NumArray numArray = new NumArray([1, 3, 5]);
numArray.sumRange(0, 2); // 返回 1 + 3 + 5 = 9
numArray.update(1, 2); // nums = [1,2,5]
numArray.sumRange(0, 2); // 返回 1 + 2 + 5 = 8
提示:
1 <= nums.length <= 3 * 10^4
-100 <= nums[i] <= 100
0 <= index < nums.length
-100 <= val <= 100
0 <= left <= right < nums.length
調用 pdate 和 sumRange 方法次數不大于 3 * 10^4
來源:力扣(LeetCode)
解題思路
??這類題乍一看如果不考慮實際情況,假設一個理想的算力內存無限的情況下可以非常簡單的直接寫出來。
class NumArray:def __init__(self, nums: List[int]):self.nums=numsdef update(self, index: int, val: int) -> None:self.nums[index]=valdef sumRange(self, left: int, right: int) -> int:return sum(self.nums[left:right+1])# Your NumArray object will be instantiated and called as such:
# obj = NumArray(nums)
# obj.update(index,val)
# param_2 = obj.sumRange(left,right)
??但是這也的后果往往是超時的:
??一個簡單的優化就是仿照分塊查詢來降低算法的時間復雜度,以一定的空間來換取時間。假設以分塊來解決這樣的題目,那么一個塊內需要放多少元素呢?這個可以從時間復雜度的分析得出一個理論上的最優解,此題的初始化和更新值的操作需要的時間復雜度分別為O(n)和O(1),而求和的復雜度如果以上面的操作來算的話是O(left-right),也是O(n)的級別,所以每次求和十分耗費時間(因為初始化只需要一次,相對調用次數較少,無需考慮初始化的優化),分塊的話假設一個塊的大小為A,那么考慮一個最普通的情況right和left跨越三個塊其時間復雜度就是O(A+n/A),當且僅當A取根號n的時候時間復雜度最小。
class NumArray:def __init__(self, nums: List[int]):self.blockSize=math.ceil(math.sqrt(len(nums)))self.sums=[0]*(len(nums)//self.blockSize+1)for i in range(len(nums)):self.sums[i//self.blockSize]+=nums[i]self.nums=numsdef update(self, index: int, val: int) -> None:self.sums[index//self.blockSize]+=val-self.nums[index]self.nums[index]=valdef sumRange(self, left: int, right: int) -> int:if left//self.blockSize==right//self.blockSize:return sum(self.nums[left:right+1])return sum(self.nums[left:(left//self.blockSize+1)*self.blockSize])+sum(self.sums[left//self.blockSize+1:right//self.blockSize])+sum(self.nums[right//self.blockSize*self.blockSize:right+1])# Your NumArray object will be instantiated and called as such:
# obj = NumArray(nums)
# obj.update(index,val)
# param_2 = obj.sumRange(left,right)
總結
以上是生活随笔為你收集整理的LeetCode中等题之区域和检索 - 数组可修改的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: LeetCode简单题之整理字符串
- 下一篇: LeetCode简单题之找出两数组的不同