leetcode 307. Regional and retrieve - array can be modified
Given an array of integers nums, the array element from the sum of the index i to j within the range of elements (i ≤ j), comprising i, j points.
update (i, val) function can be updated by the value of the subscript i is val, thus the number of columns to be modified.
Example:
Given nums = [1, 3, 5] sumRange(0, 2) -> 9 update(1, 2) sumRange(0, 2) -> 8
Source: stay button (LeetCode)
link: https: //leetcode-cn.com/problems/range-sum-query-mutable
copyrighted by deduction from all networks. Commercial reprint please contact the authorized official, non-commercial reprint please indicate the source.
Tree line on Baidu Encyclopedia definition:
Segment tree is a
binary search tree
, and the
interval tree
is similar, it means a section partitioned into intervals, a leaf node corresponding to each unit section of the segment tree.
For each non-segment tree
leaf node
[a, b], the interval its left son represented by [a, (a + b) / 2], segment the right son represented by [(a + b) / 2 + 1, b]. Therefore segment tree is
a balanced binary tree
, the last number of child nodes is N, i.e., the entire length of the line section.
Using the segment tree can quickly find a particular node number appearing in a number of line segments, the
time complexity
of O (logN). Without the optimization of
space complexity
is 2N, so sometimes need to make discrete space compression.
Since the subject of a considerable number of operations on the array to be modified:
(1) If the original data structure directly, i.e., modify the array, each modification will take O (1), each time interval and outputs will take O (n) time complexity
(2) But when we set up an interval and the tree line, and the output of each modification will take O (logn) time complexity
A binary tree structure to organize segment tree:
class NumArray { TreeNode* root; vector<int> num; int n; public: NumArray(vector<int>& nums) { n=nums.size()-1; num=nums; if(n>=0) root=creatTree(nums,0,n); //针对初始化时数组为[[]] } TreeNode* creatTree(vector<int>& nums,int x, int y ) { if(x==y) { TreeNode* tmp=new TreeNode(nums[x]); return tmp; } else { int sum=0; for(int i=x;i<=y;i++) { sum+=nums[i]; } TreeNode* tmp = new TreeNode(sum); int mid=(x+y)/2; tmp->left=creatTree(nums,x,mid); tmp->right=creatTree(nums,mid+1,y); return tmp; } } void update(int i, int val) { TreeNode* r=root; int leftBorder=0,rightBorder=n; while(r) { r->val=r->val-num[i]+val; int mid = (leftBorder+rightBorder)/2; if(i<=mid) { r=r->left; rightBorder=mid; } else { r=r->right; leftBorder=mid+1; } } num[i]=val; } int sum(TreeNode* r, int i, int j, int leftBorder, int rightBorder) { if(r==NULL)return 0; if(i==leftBorder&&j==rightBorder)return r->val; int mid = (leftBorder+rightBorder)/2; if(i<=mid&&j>mid) { return sum(r->left, i, mid, leftBorder, mid)+sum(r->right, mid+1, j, mid+1, rightBorder); } else if(i<=mid) { return sum(r->left, i, j, leftBorder, mid); } else if(i>mid) { return sum(r->right, i, j, mid+1, rightBorder); } return INT_MAX; } int sumRange(int i, int j) { TreeNode* r=root; return sum(r, i ,j, 0, n); } }; /** * Your NumArray object will be instantiated and called as such: * NumArray* obj = new NumArray(nums); * obj->update(i,val); * int param_2 = obj->sumRange(i,j); */
Fenwick tree with organized segment tree:
class NumArray { vector<int> segmTree;; int n; public: NumArray(vector<int>& nums) { n=nums.size()-1; if(n >= 0) buildSegmTree(nums,0,0,n); } //自底向上建树 void buildSegmTree(vector<int>& nums,int cur, int begin, int end ) { while(cur >= segmTree.size())segmTree.push_back(0); if(begin == end) { segmTree[cur] = nums[begin]; } else { int mid = (begin + end) / 2; int left = cur * 2 + 1; //左子区间下标 int right = cur * 2 + 2; //右子区间下标 buildSegmTree(nums,left,begin,mid); buildSegmTree(nums,right,mid+1,end); segmTree[cur] = segmTree[left] + segmTree[right]; } }
//自底向上更新 void updateSegmTree(int cur, int begin, int end, int i, int val) { if(begin > end)return; if(begin == end) { segmTree[cur]=val; return; } int mid = (begin + end) / 2; int left = 2 * cur + 1; int right = 2 * cur +2; if(i <= mid && i >= begin) { updateSegmTree(left, begin, mid, i, val); } else { updateSegmTree(right, mid+1, end, i, val); } segmTree[cur] = segmTree[left] + segmTree[right]; } void update(int i, int val) { updateSegmTree(0, 0, n, i, val); }
//自顶向下找区间 int sum( int cur, int i, int j, int begin, int end) { if(i > end || j < begin)return 0; if(i <= begin && j >= end) return segmTree[cur]; int mid = (begin + end) / 2; int left = cur*2 + 1; int right = cur*2 + 2; return sum(left, i, j, begin, mid)+sum(right, i, j, mid+1, end); } int sumRange(int i, int j) { return sum(0, i ,j, 0, n); } };