lintcode--区间求和 I
2017-10-18 17:42
393 查看
给定一个整数数组(下标由 0 到 n-1,其中 n 表示数组的规模),以及一个查询列表。每一个查询列表有两个整数 [start, end] 。 对于每个查询,计算出数组中从下标 start 到 end 之间的数的总和,并返回在结果列表中。
样例
对于数组 [1,2,7,8,5],查询[(1,2),(0,4),(2,4)], 返回 [9,23,20]
思路分析:
这里首先看到的第一想法就是暴力法直接将其对应的范围之间的数加在一起,然后将添加进向量器中,但是这样时间会是个问题,果然程序运行到91%的时候,显示时间不够。然后根据注意事项提示,选择用线段树来进行计算,线段树的构造的时间复杂度是o(n),查找时间复杂度是log(n),这样时间就会减少很多。这里主要的函数只有两个一个是构造线段树,一个是查找线段树。构造的时候这里添加了一个sum成员存储某一段的值,构造是用递归的方法,如果是叶子结点就将其对应数组中的值赋给sum,如果不是叶子结点就将左右节点sum值的和赋给该节点的sum。这样就构造成功了。查找的时候,就按照上面建立线段树的过程查找也是利用递归,但是这里可能会有一点点不同,就是如果区间在某一个节点的两边,我们就需要将区间分为两段在进行查找。如果查找的范围线段树里刚好有就直接返回。如果没有就将其对应的不同线段的和加在一起就得到了查找的结果。
代码如下:
注意点:
返回值的范围一定要注意,因为这里返回值的类型是long long类型,所以记得将查找区间的结果的返回类型设为long long
样例
对于数组 [1,2,7,8,5],查询[(1,2),(0,4),(2,4)], 返回 [9,23,20]
思路分析:
这里首先看到的第一想法就是暴力法直接将其对应的范围之间的数加在一起,然后将添加进向量器中,但是这样时间会是个问题,果然程序运行到91%的时候,显示时间不够。然后根据注意事项提示,选择用线段树来进行计算,线段树的构造的时间复杂度是o(n),查找时间复杂度是log(n),这样时间就会减少很多。这里主要的函数只有两个一个是构造线段树,一个是查找线段树。构造的时候这里添加了一个sum成员存储某一段的值,构造是用递归的方法,如果是叶子结点就将其对应数组中的值赋给sum,如果不是叶子结点就将左右节点sum值的和赋给该节点的sum。这样就构造成功了。查找的时候,就按照上面建立线段树的过程查找也是利用递归,但是这里可能会有一点点不同,就是如果区间在某一个节点的两边,我们就需要将区间分为两段在进行查找。如果查找的范围线段树里刚好有就直接返回。如果没有就将其对应的不同线段的和加在一起就得到了查找的结果。
代码如下:
/** * Definition of Interval: * classs Interval { * int start, end; * Interval(int start, int end) { * this->start = start; * this->end = end; * } */ class SegmentTreeNode1{ public: int start, end; long long sum; SegmentTreeNode1 *left, *right; SegmentTreeNode1(int start, int end) { this->start = start; this->end = end; this->sum = 0; this->left = this->right = NULL; } }; class Solution { public: /* * @param A: An integer list * @param queries: An query list * @return: The result list */ vector<long long> intervalSum(vector<int> &A, vector<Interval> &queries) { // write your code here vector<long long>res; SegmentTreeNode1 *head=build(A,0,A.size()-1); for(int i=0;i<queries.size();i++) { res.push_back(query(head,queries[i].start,queries[i].end)); } return res; } //线段树的构建 SegmentTreeNode1 * build(vector<int> &A,int start, int end) { // write your code here SegmentTreeNode1 * head=new SegmentTreeNode1(start,end); if(start==end) { head->sum=A[start]; return head; } head->left=build(A,start,(start+end)/2); head->right=build(A,(start+end)/2+1,end); head->sum=head->left->sum+head->right->sum; return head; } //区间查找 long long query(SegmentTreeNode1 * root, int start, int end) { // write your code here if(!root) return INT_MIN; if(start==root->start&&end==root->end) { return root->sum; } int mid=(root->start+root->end)/2; if(mid<start) { return query(root->right,start,end); } else if(end<mid+1) { return query(root->left,start,end); } else { return query(root->left,start,mid)+query(root->right,mid+1,end); } } };
注意点:
返回值的范围一定要注意,因为这里返回值的类型是long long类型,所以记得将查找区间的结果的返回类型设为long long
相关文章推荐
- [Lintcode]Interval Sum II区间求和 II
- 区间求和 I -LintCode
- lintcode-区间求和I-206
- lintcode(207)区间求和 II
- 区间求和 II -LintCode
- lintcode-206-区间求和 I
- LintCode:区间求和
- 树链剖分&树状数组区间加减区间求和模板
- 树状数组区间求和三种模型
- nyoj1115-士兵杀敌(二)(线段树单点更新,区间求和)
- 伸展树(插入区间,修改区间,区间置数,区间反转,区间求和,连续最大和)BZOJ1500
- poj 3468 A Simple Problem with Integers 线段树 区间更新求和
- kuangbin专题七:E题 Just a Hook ( 延迟标记,区间更新(赋值)求和 )
- poj 3468 A Simple Problem with Integers 【线段树成段更新 + 区间求和】
- POJ 1195 Mobile phones 线段树 二维线段树 单点更新 区间求和
- lintcode(221)链表求和 II
- 【模板】树状数组 区间修改,区间求和 (模板题:洛谷P3372线段树1)
- zzulioj--1827--石锅全拌(区间求和水题)
- [学习笔记] 树状数组区间加+区间求和
- *[Lintcode]Interval Minimum Number 区间最小数