Q:
Given an integer array nums, find the sum of the elements between indices i and j (i ≤ j), inclusive.
The update(i, val) function modifies nums by updating the element at index i to val.
Example:
Given nums = [1, 3, 5]
sumRange(0, 2) -> 9
update(1, 2)
sumRange(0, 2) -> 8
Note:
The array is only modifiable by the update function.
You may assume the number of calls to update and sumRange function is distributed evenly.
題意大致是,給你提供一個二維數組,然後求指定下標之間的數之和,已知數組中的值可以更新,並且更新和求和操作會被頻繁調用
Solution;
別看這道題和上幾道題相似,解法其實完全不一樣, (LeetCode 303) Range Sum Query - Immutable。
最原始的想法就是暴力遍歷求和,不過想也不用想,當求和操作操作頻繁調用,會超出給定時限。
並且,數組中的值會被頻繁更新,我瞭解到的解決方法有Segement Tree(線段樹),Binary Indexed Tree(樹狀數組) ,和平方根分解三種辦法。樹狀數組真的是神作,很精巧的辦法,也很高興能夠了解並學習這些數據結構。
我在這裏提供線段樹的解法,想了解樹狀數組的解法可以參考這篇博客:
(LeetCode 307) Range Sum Query - Mutable(樹狀數組講解)
線段樹,顧名思義,它的每一個結點代表一個區間。每個結點中包含的信息應該有該區間的起始下標
我們這道題就使用到了
class NumArray {
public:
struct SegmentNode
{
int start;
int end;
int sum;
SegmentNode *left;
SegmentNode *right;
SegmentNode(int start, int end){
this->start = start;
this->end = end;
this->sum = 0;
}
};
SegmentNode *root;
SegmentNode* buildTree(vector<int> &nums,int lo,int hi){
if(hi<lo)return nullptr;
SegmentNode *node = new SegmentNode(lo,hi);
if(hi==lo){
node->sum = nums[lo];
return node;
}
int mid = (lo+hi)/2;
node->left = buildTree(nums,lo,mid);
node->right = buildTree(nums,mid+1,hi);
node->sum = node->left->sum+node->right->sum;
return node;
}
void update(SegmentNode *node, int po,int val){
if(node->start==node->end&&node->start == po){
node->sum = val;
return;
}
if(po<node->start||po>node->end)
return;
int mid = (node->start+node->end)/2;
if(po<=mid){
update(node->left,po,val);
}
else{
update(node->right,po,val);
}
node->sum = node->left->sum + node->right->sum;
}
int sumRange(SegmentNode *node, int lo, int hi){
if(node->start==lo&&node->end ==hi)
return node->sum;
int mid = (node->start+node->end)/2;
if(hi<=mid) return sumRange(node->left,lo,hi);
else if(lo>mid) return sumRange(node->right,lo,hi);
else return sumRange(node->left,lo,mid)+sumRange(node->right,mid+1,hi);
}
NumArray(vector<int> &nums) {
this->root = buildTree(nums,0,nums.size()-1);
}
void update(int i, int val) {
update(root,i,val);
}
int sumRange(int i, int j) {
return sumRange(root,i,j);
}
};
不過時間消耗不那麼樂觀啊
Reference Link:
http://www.cnblogs.com/yrbbest/p/5056739.html